What we mean by an attack surface
An attack surface is not a vague weakness. It is a specific point in code where an AI agent can trigger a dangerous capability: a place the agent can actually do something to the outside world.
Every surface is classified against a fixed capability vocabulary, so the same thing is always counted the same way. We group them into three families:
Code & system
code_exec · subprocess_exec
deserialize · ssti
file_delete · file_perms
Money & data out
payment · blockchain_tx
secret_exfil · cloud_write
external_write
Agent actions
tool_invoke · email_send · dm
post · telegram_send
browser_click · computer_use · queue_mutation
In scope
Command and code execution, deserialisation RCE, agent tool invocation, outbound sends, data mutation, payments and crypto, network egress and SSRF, computer and browser use, and dynamic config or module loading.
COUNTEDOut of scope
Pure reads, object constructors, logging, and deprecated no-ops. If it cannot change the world or leak from it, it is not counted. This is written down as a rubric, not decided case by case.
NOT COUNTEDA worked example
A bundled tool exposes subprocess.run(cmd) where cmd is built from text the agent read off a web page. That single call is one surface, capability subprocess_exec.
ONE CALL · ONE SURFACEThe engine gets stricter over time — without inflating false positives.
A suggestive variable name proves nothing here. A traced path does.
From finding to fix
A concrete plan, enforced at runtime
For every unguarded surface, Hermes Shield generates a concrete fix plan: the exact control required (for example a kill-switch guard, a final action gate and an approved-hash check), the file to change, and a test to prove the surface is closed. The action gate then enforces it at runtime.
To be plain about scope: today the repairer plans the fix and the runtime gate enforces it. It is not a black-box that silently rewrites your code. A human stays in the loop on the change, which is exactly where we think a security tool should sit.
HUMAN IN THE LOOPThe method is only worth trusting if we tell you its edges.
0 proven-live
Across all 12 frameworks we claim zero proven-live exploits, because none has cleared the human-trace-plus-proof bar. A security company that overclaims is part of the problem.
Reachable is not exploitable
474 is static reachability in real code. It is a strong signal and a floor, not a demonstration that an attack succeeds on your systems.
We contain, not prevent
We do not stop prompt injection. We stop the action it tries to cause. Our anchor is OWASP LLM06, Excessive Agency, the last line of defence.
Python-first, and honest about it
The guard and reachability model is strongest in Python. Other languages are reported as sinks only, and never dressed up as fully rated.
Corrections only remove
When we corrected our own counts, every change could only remove a false positive, never add a finding. The number went down, on purpose.
Residual risk is documented
Security is probabilistic, not absolute. We write down what we observed and what we did not, rather than implying invulnerability.
Straight answers
The questions a security lead asks before trusting a number.