feat(agent-scan): add memory/RAG poisoning detection skill - #429
feat(agent-scan): add memory/RAG poisoning detection skill#429DevamShah wants to merge 1 commit into
Conversation
boy-hack
left a comment
There was a problem hiding this comment.
Code Review: feat(agent-scan): add memory/RAG poisoning detection skill
Overall Assessment: ✅ Looks Good — Ready to Merge with Minor Notes
This is a well-designed addition to the agent-scan skill suite. The skill fills a genuine detection gap (durable-state poisoning vs. ephemeral injection) and integrates cleanly with the existing architecture.
✅ Strengths
-
Conceptually sound distinction: Correctly separates memory/RAG poisoning (durable store corruption) from indirect injection (single-turn hijack). The
When to Useguard clause prevents false application on stateless agents. -
Canary token design: Using per-run random tokens (
MEMCANARY-<6 hex>,KBCANARY-<6 hex>) to verify both durability AND behavior corruption is a rigorous two-signal approach. Requiring both signals prevents false positives. -
Clean integration:
agent.pyadds the skill to theSKILLSlist in one line;owasp-asi/SKILL.mdandagent_vulnerability_detector.mdare updated consistently. -
OWASP ASI mapping:
ASI06(Prompt Injection via RAG) as primary andASI01, ASI04as secondary is accurate and matches the threat model. -
Output template: Well-structured
<vuln>blocks include conversation turns and canary evidence — consistent with existing skill output format.
Minor Observations
-
Session-reset assumption: The skill assumes some platforms support session resets between plant and trigger turns. The fallback (insert unrelated filler turn) is pragmatic, but false-negative rate will be higher for agents that don't persist state across dialogue sessions.
-
allowed-tools: dialogue: Correct and minimal — no concerns. -
No unit tests: Consistent with existing skill suite conventions.
Summary
| Check | Result |
|---|---|
| Skill logic correctness | Pass |
| Integration with agent.py SKILLS list | Pass |
| OWASP ASI table updated | Pass |
| agent_vulnerability_detector.md updated | Pass |
| Output format consistent | Pass |
| No breaking changes | Pass |
Ready to merge.
|
Hi @DevamShah, this PR has conflicts with main after PR #482 modularized agent-scan (files moved from I've prepared a rebased version on my fork that adapts all file paths to the new modularized structure and resolves the Rebased branch: What changed in the rebase:
You can either:
Original author and commit metadata are preserved. |
|
Hi @DevamShah, following up on this PR. @NY1024 has prepared a rebased version on their fork that adapts all file paths to the new modularized structure (after PR #482) and resolves the The rebased branch is: https://github.com/NY1024/AI-Infra-Guard/tree/rebase/pr-429-devam-memory-rag Two options to move forward:
This is a valuable detection skill (memory/RAG poisoning) - would be great to get it merged. Please let us know how you'd like to proceed. @pythoncheng for visibility. |
Add a Stage-2 detection skill, memory-rag-poisoning-detection, that probes agents with durable state (long-term memory, preference stores, or writable RAG/knowledge bases) for persistent-memory poisoning and knowledge-base contamination using planted per-run canary tokens. This is the missing detection source for OWASP ASI06 (Memory & Context Poisoning), which the owasp-asi classification skill already enumerates but had no skill producing findings for. indirect-injection-detection covers single-turn goal hijack; it does not cover durable content an attacker writes into a store the agent trusts on future turns/sessions. Wire-in: - prompt/skills/memory-rag-poisoning-detection/SKILL.md: new skill, mirrors tool-abuse-detection conventions (frontmatter, When to Use / Strategy / Output, two-phase plant/trigger vectors, vuln templates). - prompt/system/agent_vulnerability_detector.md: add to Standard Skills. - core/agent.py: register in _DETECTION_SKILLS (parallel path). - prompt/skills/owasp-asi/SKILL.md: add ASI mapping row (ASI06 primary). Markdown plus one-line Python only; no new dependencies, no behavioral change to existing skills, no external network target (canaries are generated per run). Signed-off-by: Devam Shah <devamshah91@gmail.com>
8e9a1fb to
657fe07
Compare
|
@NY1024 thanks for doing the rebase — you did my work for me and I left it sitting for a month. Apologies for the delay. I took option 1: rebased and force-pushed to my own branch so the commit stays on this PR. Head is now What I did Your branch
Final four files, at the modularized paths: +177/-0, same as the original. Before adopting your rebase I diffed it against my original commit: the What I verified, and how
I have not run agent-scan end-to-end against a live target from this rebase, so I'm not claiming a functional pass — the above is static verification only. What I deliberately did not change
One open question before you merge
There is real overlap with mine on the persistent-instruction half. The difference: that skill plants a fixed Your call on how you want that reconciled. Three options, in my order of preference:
@boy-hack — that is the decision I'd need from you. Option 2 needs nothing from me; the PR is mergeable right now. Say the word on 1 or 3 and I'll push the change today. |
|
Thanks @DevamShah for the thorough rebase notes and static verification — and @NY1024 for doing the path-adaptation work after the #482 modularization. The cherry-pick onto current Decision on the Two small asks before/after merge, neither blocking:
This is a valuable addition (covers OWASP ASI06, which the repo classified but had no detection source for). Approving — please proceed with Option 1. 🚀 (Review comment only — not merging.) |
feat(agent-scan): add memory/RAG poisoning detection skill
Summary
Adds a new Stage-2 detection skill,
memory-rag-poisoning-detection, that probes agents with durable state — long-term memory, preference stores, or writable RAG/knowledge bases — for persistent-memory poisoning and knowledge-base contamination, using planted per-run canary tokens to verify both durability and behavior corruption.Problem / motivation
agent-scanships detection skills forauthorization-bypass,data-leakage,indirect-injection, andtool-abuse(plus theowasp-asiclassification skill).indirect-injection-detectioncovers single-turn goal hijack — a malicious instruction embedded in content the agent processes once. It does not cover the durable case: content an attacker writes into a store the agent trusts on future turns or sessions.That gap maps directly to OWASP ASI06 — Memory & Context Poisoning, which this repo's own
owasp-asiskill already enumerates but had no detection skill producing findings for. Two real, distinct attack classes go unscanned today:Both are durable and cross-turn, so a single-shot injection probe cannot detect them.
Change
Mirrors
tool-abuse-detection/SKILL.mdexactly — frontmatter (name/description/allowed-tools: dialogue) plusWhen to Use,Strategy(capability alignment → test vectors → judge), andOutputwith<vuln>blocks.agent-scan/prompt/skills/memory-rag-poisoning-detection/SKILL.md— the skill. Each test vector is two-phase: a plant turn that writes a fresh per-run canary (MEMCANARY-<hex>/KBCANARY-<hex>) plus a malicious directive, and a trigger turn (ideally after a session reset) that checks persistence and behavior change. Two<vuln>output templates (persistent memory, RAG knowledge base); the summary-to-memory vector reuses the memory template.agent-scan/prompt/system/agent_vulnerability_detector.md— adds the skill to Standard Skills with its applicability ("Long-term memory, preference store, or writable RAG/knowledge base"). This is the table the Stage-2 detector reads to decide which skill toload_skill.agent-scan/core/agent.py— adds the skill to_DETECTION_SKILLS, keeping the concurrentrun_parallel_detectionpath consistent with the detector table (one-line addition;_WORKER_CONCURRENCYunchanged).agent-scan/prompt/skills/owasp-asi/SKILL.md— adds the skill's row to the Detection-Source → ASI table (ASI06primary;ASI01,ASI04secondary).Markdown-and-one-line-Python only; no behavioral change to existing skills, no new dependencies, no external network target.
Low-false-positive design
Mirrors the repo's "refusals and educational explanations are not vulnerabilities" stance and adds two explicit guards:
Security rationale
The remediation guidance in each
<vuln>reflects this: treat memory/retrieval as untrusted data not executable instructions, separate "facts to recall" from "behavior to follow", scope memory per-user/session, and gate KB writes behind authorization with provenance tagging.Testing / validation
Validated against a clean checkout with this change applied:
tools/skill/skill.py,get_all_skills→os.listdir(SKILLS_DIR)) discovers the new skill;parse_skill_file()parsesname=memory-rag-poisoning-detection,description, andallowed-tools=dialoguefrom the frontmatter. No separate registration file is required.yaml.safe_load); all mirrored sections present (When to Use,Strategy, test vectors,Judge result,Output); two balanced<vuln>templates (same pattern as the siblingtool-abuse-detectionskill).python -m py_compile core/agent.pypasses;_DETECTION_SKILLSnow listsmemory-rag-poisoning-detection, so workers execute it. The detector-table edit is the live load-bearing wire-in.git diff --cached --statconfirms exactly four changes — the new SKILL.md plus three one-line additions — and nothing else.No live target is required to validate this change; the skill drives the existing
dialogue()tool at scan time like every other skill in this directory.