▸ agent_security_research

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.

12frameworks audited
8,447action surfaces mapped
596reachable-in-repo
542install-liability (distinct tier)
pip install hermes-shield-scanner

then hermes-shield demo · v0.8.2 · PyPI · GitHub

then run hermes-shield scan in your own repo · report date 2026-07-05 · pinned commits

▸ twelve_frameworks_audited

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.

FrameworkAction surfacesReachable-in-repoInstall-liabilityNote
▸ agno1,76313120
▸ letta1,40114134
▸ llama_index1,10811626the pattern here once reached eval() — CVE-2023-39662, since patched.
▸ cua1,08121261computer-use execution path — the largest install-liability tier of the set.
▸ langflow9231547
▸ semantic-kernel920915
▸ potpie5751534
▸ SuperAGI3662022
▸ notte136013
▸ julep102321
▸ babyagi80211
▸ RA.Aid54116
Total (12)8,447596542

▸ 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.

▸ inherited_attack_surface

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

0
frameworks audited
static · read-only · pinned commits
0
action surfaces mapped
counted in default-install source
0
reachable-in-repo
a distinct tier · default config
0
install-liability
a distinct tier · reachability we cannot rule out, live on install
▸ methodology

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.

▸ the_honest_part

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.

▸ 0

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.

▸ ro

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.

Abstract warm figures — the audited framework surface, visualised
▸ proven_live_exploits_claimed
Zero. On purpose.
▸ the_argument

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

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 scan
▸ customer_zero_learned_this_the_hard_way

Your 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.

FREE SCANNER · LIVE · LOCAL-FIRST · AUDITABLE
Agent Framework Attack-Surface Report — Hermes Shield