agentsec · Tools · memfence

Offline · stdlib-only · MIT

memfence: detect poisoning in persistent agent memory in AI agents


Offline persistent agent-memory / store poisoning scanner.

What it detects

Offline persistent agent-memory / store poisoning scanner.

Agent memory stores (mem0 exports, LangGraph checkpoints, custom fact JSONL, Assistants-style memory files, plain-text dumps) are re-injected into later sessions. A single poisoned entry can override instructions, plant exfil bait, smuggle hidden Unicode, or demand "always remember / from now on" persistence. memfence reviews *saved memory dumps* and reports findings with per-entry attribution.

Standard library only. It never connects to a network and never writes to the store.

Rules

RuleSeverityWhat it flags
MF01highOverride / jailbreak phrasing planted in memory
MF02highFake role / system / developer tokens
MF03criticalHidden Unicode (zero-width, bidi, TAG) — escalates when decoded text is instruction-like
MF04highExfil / callback URL bait (webhook, oast, ${API_KEY} in URL, …)
MF05highCredential / secret harvest instructions
MF06highTool-chaining / consequential-action bait (shell, deploy, pay, transfer)
MF07highConceal-from-user / silently instructions
MF08mediumBase64/hex blob that decodes to instruction-like text
MF09criticalCross-session persistence bait (always remember, from now on you must, update your system prompt, every future session)
MF10infoInventory of memory entries scanned (disable in CI with --disable MF10)
MF11highDelayed / trigger-phrase backdoor (after N messages, when the user says X, then exfil or harvest)
MF12highStructural memory poison: payment-swap, pipe-to-shell, or a planted payroll/login portal that forwards session cookies
MF13highAuto-approve / confirmation-bypass policy planted for privileged tools (shell, write_file, …)
MF14mediumPlanted impossible user identity (age outside a realistic living-person range)

Usage

python3 memfence.py memory.json [more.jsonl dir/ -]
  --as-text           treat inputs as plain-text dumps (paragraph = entry)
  --disable RULE ...  skip rule ids (e.g. MF10 MF08)
  --json              machine-readable output
  --min-severity S    hide findings below S (default info)
  --fail-on S         exit 1 if any finding >= S (default high; any, none)
  --list-rules

After pip install of the kit, the same options work as agentsec memfence …. Every tool also accepts --help and almost every tool accepts --json.

Example output

Flags MF09/MF01 on the persistence entry, MF04/MF05 on the webhook exfil entry, MF06 on the shell-tool bait, MF07 on conceal-from-user, MF02/MF01 on the fake role token, MF05 on credential harvest (exit 1).

examples/clean_memory.json is clean under --fail-on high (exit 0). See also poisoned_unicode.json (MF03 TAG/bidi/ZW), poisoned_encoded.json (MF08), poisoned_facts.jsonl, poisoned_langgraph.json, and poisoned_plaintext.txt --as-text.

python3 memfence.py examples/poisoned_mem0.json --disable MF10

SARIF and CI

agentsec memfence path/to/input --sarif > memfence.sarif

# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
  with:
    tools: memfence
    paths: path/to/input
    fail-on: high

SARIF 2.1.0 can be uploaded to GitHub code scanning. The composite action writes per-tool reports under agentsec-sarif/ by default.

OWASP mapping

Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.

Known limits

evade detection; benign ops notes that say "always remember the runbook URL" can false-positive MF09/MF04 — review snippets.

without the source text are invisible.

Full source, tests, and fixtures: tools/memfence/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.