We read the source. We counted the blast radius.
An attack-surface report on twelve open-source agent frameworks. We counted the action surface each ships, how much an untrusted prompt can reach, and how much goes live the moment you install — and one free command shows you the same map in your own repo.
pip install hermes-shield-scannerthen hermes-shield demo · v0.8.2 · PyPI · GitHub
then run hermes-shield scan in your own repo · report date 2026-07-05 · pinned commits
What ships when you pip install an agent
Static, read-only reading of each framework at a pinned commit. Three counts per framework: the action surface it ships, how much of it an untrusted prompt can reach inside the repo, and how much is install-liability — live the moment the package lands. These are counts, not a safe-versus-dangerous grade.
| Framework | Action surfaces | Reachable-in-repo | Install-liability | Note |
|---|---|---|---|---|
| ▸ agno | 1,763 | 131 | 20 | |
| ▸ letta | 1,401 | 141 | 34 | |
| ▸ llama_index | 1,108 | 116 | 26 | the pattern here once reached eval() — CVE-2023-39662, since patched. |
| ▸ cua | 1,081 | 21 | 261 | computer-use execution path — the largest install-liability tier of the set. |
| ▸ langflow | 923 | 15 | 47 | |
| ▸ semantic-kernel | 920 | 9 | 15 | |
| ▸ potpie | 575 | 15 | 34 | |
| ▸ SuperAGI | 366 | 20 | 22 | |
| ▸ notte | 136 | 0 | 13 | |
| ▸ julep | 102 | 3 | 21 | |
| ▸ babyagi | 80 | 2 | 11 | |
| ▸ RA.Aid | 54 | 1 | 16 | |
| Total (12) | 8,447 | 596 | 542 |
▸ counts summarise the default install at a pinned commit — read-only static analysis, no exploit run. Reachable-in-repo (596) and install-liability (542) are two distinct tiers, not a subset of one another. Verified lower bounds. Full methodology on public scans.
Install one framework. Inherit its whole surface.
Every app built on these frameworks starts with these numbers — before a single line of its own code.
▸ OWASP LLM06 · Excessive Agency — measured, not asserted
What we measured, and what we did not
measured: surfaces
Code paths where model output becomes an action — file writes, network calls, code execution, tool dispatch — counted in the source of the default install.
measured: reachability
8,447 action surfaces mapped across 12 frameworks. Of those, 596 are reachable-in-repo and 542 are install-liability — two distinct tiers, not a subset of one another (install-liability is reachability we cannot rule out, live on install). Reachable is not the same as exploited — and we say so.
measured: install-liability
Of the mapped surface, how much goes live the moment the package is installed — 542 across the twelve. A count of what ships hot, not a grade of any team's gating.
not measured: live exploits
We did not attack anyone's production system, weaponise a finding, or publish proof-of-concept exploits. Zero live systems were touched.
not measured: runtime behaviour
This is static analysis. We read source; we did not instrument deployed agents. Runtime posture can be better — or worse — than the code suggests.
not measured: intent
No maintainer is at fault. These frameworks optimise for capability, and openly document it. The gap is structural, not negligent.
Read the caveats before you quote the numbers
A security report you can't audit is marketing. So here is exactly how far the evidence goes — and no further.
proven-live exploits
We claim zero proven-live exploitations of these surfaces. That number is a feature of this report, not a weakness. We count exposure, not casualties.
read-only, static
Every finding comes from reading source code. No fuzzing of live services, no credentials used, no systems probed. You can reproduce the whole audit from a git clone.
pinned commits
Each framework was audited at a pinned commit, recorded per finding. Maintainers ship fixes constantly — check the pin before assuming a number still holds.
Why one shared layer
542 surfaces across 12 frameworks means every team patching alone patches 542 times. A single action-control layer — Map → Trace → Prove → Block → Patch — sits where the frameworks converge: the moment an agent acts.
fix at the source
- One gate on the action path
- Protects every downstream install at once
- Beats a thousand bespoke wrappers that drift out of date
framework-agnostic
- The frameworks disagree on everything except one thing
- Model output eventually becomes an action
- The one place a control can be universal
local-first
- The layer runs where your agents run
- Local-first by design; the audit trail is yours
- Kill switch, action gates, threat shield — coming (Shield runtime)
Your repo here — scan it yourself, free.
The free scanner is live. Point it at your own agent codebase and get the same map, same method, same honesty — the number that matters is yours: what your agents inherited the day you installed them.
A default scan runs fully local and reads your code read-only — nothing is sent anywhere. The optional --ai tier uses your own local Claude CLI; that's the only mode that sends any code off your machine, and only to Anthropic's API under your own Claude account.
pip install hermes-shield-scanner
cd your-agent-repo && hermes-shield scanYour agent has this surface too.
We built Shield because our own agent got prompt-injected. If your stack imports any framework on this page, you inherited these numbers the day you shipped. The free scanner shows you yours — run it in a minute.