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
| Rule | Severity | What it flags |
|---|---|---|
| MF01 | high | Override / jailbreak phrasing planted in memory |
| MF02 | high | Fake role / system / developer tokens |
| MF03 | critical | Hidden Unicode (zero-width, bidi, TAG) — escalates when decoded text is instruction-like |
| MF04 | high | Exfil / callback URL bait (webhook, oast, ${API_KEY} in URL, …) |
| MF05 | high | Credential / secret harvest instructions |
| MF06 | high | Tool-chaining / consequential-action bait (shell, deploy, pay, transfer) |
| MF07 | high | Conceal-from-user / silently instructions |
| MF08 | medium | Base64/hex blob that decodes to instruction-like text |
| MF09 | critical | Cross-session persistence bait (always remember, from now on you must, update your system prompt, every future session) |
| MF10 | info | Inventory of memory entries scanned (disable in CI with --disable MF10) |
| MF11 | high | Delayed / trigger-phrase backdoor (after N messages, when the user says X, then exfil or harvest) |
| MF12 | high | Structural memory poison: payment-swap, pipe-to-shell, or a planted payroll/login portal that forwards session cookies |
| MF13 | high | Auto-approve / confirmation-bypass policy planted for privileged tools (shell, write_file, …) |
| MF14 | medium | Planted 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-rulesAfter 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.
- LLM04 Data and Model Poisoning — OWASP LLM Top 10 (2025)
- ASI06 Memory and Context Poisoning — OWASP Agentic Top 10 (2026)
Known limits
- Heuristic phrase and URL matching. Novel wording or indirect paraphrases can
evade detection; benign ops notes that say "always remember the runbook URL" can false-positive MF09/MF04 — review snippets.
- Only sees what was exported. Live vector DBs, encrypted stores, and embeddings
without the source text are invisible.
- Encoded-blob decoding is best-effort (base64/hex); other encodings are missed.
- A clean memfence result does not mean the memory backend or write-path is safe.
Full source, tests, and fixtures: tools/memfence/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.