How I Used an AI Agent's Memory to Achieve Remote Code Execution


TL;DR

  • Vulnerability: Unsanitized eval() in the agent’s memory filter leads to remote code execution (RCE).
  • Impact: Any chat prompt could trigger a server-side shell (CVSS 9.9 / Critical).
  • Root cause: Combining user-supplied filter strings with Python eval() is an AI memory injection and prompt injection issue flagged in the OWASP LLM Top 10.
  • Fix: Drop raw eval, validate LLM tool calls like external input, and sandbox the runtime.

Background: Memory as an Attack Surface

Modern AI agents keep a running memory of prior conversations to deliver context-aware responses. If the agent lets users query or filter that memory, it opens a fresh vector for AI memory injection and prompt injection attacks. This pattern is explicitly called out in the draft OWASP LLM Top 10 under Prompt Injection and Excessive Agency.


Finding the Bug with Waclaude

While field-testing Waclaude, my AI vulnerability hunter, I pointed it at an open-source AI agent with over 11,000 ⭐ and 2,000 forks. In seconds, Waclaude spotted an unsanitized eval() powering the AI agents memory. A direct path to code execution:

def _get_comparator(condition: str):
    def comparator(data: dict[str, Any]):
        return eval(condition, {}, data)  # user controlled

The condition string arrives straight from a memory_filter argument produced by the LLM, making every user prompt a potential code payload.


Deep Dive: From Memory Filter to RCE

  1. A user prompt includes a malicious filter.
  2. The LLM emits a memory_load tool call containing that filter.
  3. The agent forwards filter → _get_comparator()eval() with no validation.
  4. Python executes arbitrary code under the agent’s privileges, resulting in full remote code execution.

Proof of Concept Payload

All it took was a single-line filter embedded in a chat prompt:

__import__("os").system('echo "pwned" > /tmp/proof.txt') or False

When the agent evaluated this filter, it wrote the file, proving code execution.

Disclosure

We filed an advisory the same day, shipped a patch PR and coordinated privately with the maintainers to ship the fix. Waclaude identified, exploited and patched the vulnerability in seconds.


Key Takeaways and Mitigation

What HappenedHow to Prevent It
Raw eval() on user inputReplace with safe parsing (ast.literal_eval, vetted DSL) or whitelist operators.
LLM tool calls treated as trustedValidate and sanitize LLM output exactly like external user input.
High privileges on the hostRun agents in containers with non-root users, read-only filesystems, and syscall filters such as seccomp or AppArmor.
No automated testing for memory filtersAdd unit tests and fuzzers that inject malicious strings into every filter path.

If you’re shipping AI agents in production and want a second look at your security, let's chat!