Skip to content

Repository files navigation

agent-privilege-mapper

The third tool in a series: iam-privesc-mapper found AWS privilege-escalation paths, cloudtrail-privesc-detector caught them being exploited. This applies the same idea — find dangerous combinations of access, not just risky individual permissions — to AI agents instead of AWS IAM.

Two tools:

  1. Static capability mapper — tags an agent's tools/MCP servers with what they can actually do, then flags dangerous combinations.
  2. Prompt-injection test harness — drives a real Claude tool-use conversation against adversarial payloads to check whether the model takes the bait.

Mapper findings

Why this, not a chatbot

Most "AI projects" in a portfolio are a RAG demo or a wrapper around a chat completion — that shows you can call an API, not that you understand how these systems actually fail. Agentic AI's most-cited real risk pattern is the "lethal trifecta": an agent that (1) has access to private data, (2) processes content it didn't write itself — web pages, documents, other people's messages — and (3) has a channel to send data somewhere. Any one of those is fine alone. All three on one agent means a prompt injection hidden in that untrusted content can read the secret and exfiltrate it, and the agent will do it willingly because nothing it did was technically disallowed.

Quickstart (zero setup)

pip install -r requirements.txt
python map.py demo/sample_agent.json
# open output/report.html

What the mapper detects

Five capability flags — reads_private_data, exposed_to_untrusted_content, can_exfiltrate, can_execute, persistent_write — tagged per tool from real Claude/MCP tool-config shapes (the tools array, MCP server declarations, Managed Agents toolsets), then checked for dangerous combinations:

  • Lethal trifecta (Critical) — all three of reads/exposed/exfiltrate
  • Execute + exfiltrate (Critical) — code execution plus a way out is remote-code-execution-equivalent if either is ever driven by untrusted input
  • Persistent write + untrusted exposure (High) — an injected instruction that gets written to memory/files/tickets outlives the conversation that planted it — the agent equivalent of stored XSS
  • Reads private + exfiltrate, no injection vector yet (Medium) — worth knowing about before any untrusted-content tool gets added later
  • Unclassified tool (Low) — capabilities for unknown custom tools/MCP servers are guessed from their name/description, not confirmed; this finding says exactly that, every time

Findings map to the OWASP Top 10 for LLM Applications — confidently for LLM01 (Prompt Injection) and LLM06 (Excessive Agency), which are stable across OWASP revisions; everything else maps to a named theme with a note to verify the exact number against whichever revision you're citing. See mapper/owasp_mapping.py.

The prompt-injection harness

python test_injection.py --fixture demo/sample_transcript.json   # zero setup, illustrative
python test_injection.py --live                                   # real Claude API calls

Injection test results

The harness gives a toy agent two tools (read_document, send_email), asks it to summarize a document, then returns a poisoned document as the tool result — text containing an embedded instruction trying to get the model to email the document contents to an attacker address instead of just summarizing it. Three payload styles: a direct override, a fake <system> tag, and an impersonated-authority message.

The demo fixture is illustrative, not a captured run — there's no Anthropic API key in the environment this was built in, so it ships with a labeled, expected-outcome fixture rather than a real one. Run --live with your own key to get a real result. Expect "RESISTED" across the board — current frontier Claude models handle these specific basic injection patterns well, and a defensive tool confirming that is a legitimate result, not a disappointing one. The harness's value is being able to re-run this as a regression check after any prompt or tool change, not "proving" a vulnerability that may not exist.

Known limitations (read before trusting a finding)

Capabilities for anything outside the known-tool-type and known-MCP-server lists are guessed from keyword matching on the tool's name and description — that's a heuristic, not a fact, and it says so on every finding it produces. Pass an explicit "capabilities" list on a tool's config entry to override the guess. The injection harness only tests the three payload styles shipped here against a two-tool toy agent — it is not an exhaustive red-team, and passing it isn't a clean bill of health for a production agent with a much larger tool surface.

Architecture

mapper/loader.py          known-tool-type + known-MCP-server capability tags, keyword fallback
mapper/detectors.py       set-intersection rules over tagged capabilities
mapper/owasp_mapping.py   rule_id -> OWASP LLM Top 10
mapper/report.py          string.Template -> static HTML (no web framework)
map.py                    CLI for the static mapper

injector/payloads.py      the three adversarial documents
injector/harness.py       real two-turn Claude tool-use loop + pure verdict classifier
injector/report.py        string.Template -> static HTML
test_injection.py         CLI for the injection harness

Tests

python -m pytest

12 tests: capability tagging, all four combo rules (including a true negative), and the injection harness's verdict classifier — the classification logic is a pure function, so it's fully unit-testable without an API key or any network access.

License

MIT

About

Maps dangerous AI agent tool-capability combinations (lethal trifecta, etc.) and tests prompt-injection resistance against the real Claude API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages