June 24, 2026
Same Flaw, Opposite Verdict: AI Agents Can't Agree What Counts as a Security Vulnerability
I found three ways past an AI agent's safety gate. One was quietly fixed, two were closed as "by design" β yet the same bug class is aβ¦

By Nikos Rigas
8 min read
I found three ways past an AI agent's safety gate. One was quietly fixed, two were closed as "by design" β yet the same bug class is a credited CVE in Claude Code. The real problem: the field has no shared definition of a security boundary.
The short version
I was evaluating open-source AI agents to build a sales assistant β something that would handle confidential customer data. So I checked its security before adopting it.
Its top candidate, Hermes Agent, has a "safety gate" β the check that's supposed to stop the AI from running dangerous commands. I found three ways around it (one let an attacker run code on the host) and reported all three, with proof and fixes.
While my reports sat open, the project rewrote its security policy β downgrading that gate from a "core security boundary" to "just a heuristic, not a boundary." That re-wording mattered: under the old policy, getting past the gate was a vulnerability; under the new one, it wasn't β so my reports were closed as "out of scope." One was quietly fixed anyway, with no credit.
This isn't really about one project. Every AI agent draws the safety line in a different place β the same bug gets a CVE and a credit in one, and a shrug in another. That gap is the story.
When is a flaw a vulnerability?
In one AI agent, a flaw that lets a malicious web page run commands on your machine is a credited CVE with a fix. In another, the same class of flaw is "working as designed." Nobody's lying β they just don't agree on what counts as a vulnerability, because no one has agreed what a security boundary even is inside an AI agent.
I learned this the practical way. I was evaluating open-source AI agents to handle confidential customer data, so I tested one before trusting it: Hermes Agent, an open-source agent from Nous Research that topped my shortlist. I found three ways past its safety gate and reported them. What happened next β one quiet fix, two "out of scope" closures, and a security policy rewritten while my reports sat open β is a small window into a problem the whole field is improvising through: when you report a flaw in an AI agent, whether it "counts" depends entirely on who's holding the pen.
This is that story β and the bigger question underneath it.
Why I went looking for prompt injection first
If you're going to attack an AI agent, you start with prompt injection. It's the most common and impactful class of attack on LLM systems β OWASP tracks it as the single fastest-growing category of attack, and it has embarrassed even the top labs.
The mechanism is almost insultingly simple: an LLM can't tell its instructions apart from its data β both arrive as the same stream of text. So an attacker hides instructions inside something the agent will read: a web page, an email, a file, a chat message. The agent reads it and obeys. No exploit code. Just words.
For an agent that can run shell commands, that's the whole game. If untrusted text can steer the model, the only thing between "the model got tricked" and "your server ran the attacker's command" is the safety gate in the middle. So I went straight at the gate.
Three ways past the gate
Picture the gate as a checkpoint. Before the AI runs a command on your computer, the gate checks whether it looks dangerous β and if it does, it stops to ask you, or blocks it. It's the last thing standing between what the AI decides and what your machine actually does.
Here's all that matters for the story: I found three different ways past it. Briefly:
It could be talked into approving a command. The agent had an option to let a second AI sign off on risky commands instead of asking you. But that reviewer couldn't tell a real instruction from text hidden in the command β so a command could carry its own note ("this one's safe, approve it"), and the reviewer would go along with it.
It could be fooled by rewording. The danger-check matched commands against a list of known-bad text. Write the same dangerous command a little differently, and it wasn't on the list β so it passed.
It could be skipped entirely. The agent automatically runs any code placed in a certain folder when it starts. Since it can also create files, one planted file becomes code that runs on every launch.
None of this is far-fetched: a booby-trapped web page the agent reads could trigger any of it β and a sales assistant reads the web, email, and chat all day.
The first of these was later fixed with a small, obvious patch. Keep that in mind β it matters later.
I filed a careful report. Then the rules changed.
I wrote it all up properly β analysis, root cause, proof-of-concept, and remediation β and submitted it through the project's GitHub security advisories. Then I waited.
While I was waiting, I noticed something: the project's security policy had changed. Here is the part that matters, and all of it is public git history you can verify yourself.
On April 15, the policy said:
"The approval system tools/approval.py) is a core security boundary."
β¦and it listed prompt injection as in-scope "if it results in a concrete bypass of the approval system." My reports were precisely that.
On May 5 β after my reports were filed, while they sat open β the policy was rewritten. Its own commit message: "rewrite policy around OS-level isolation as the boundary." The approval system was now an "in-process heuristic," explicitly "not containment," and a new clause put "bypasses of in-process heuristics" out of scope.
Same file. Same code. From "core security boundary" to "not a boundary" in twenty days.
Days later, the reports were closed β citing the new policy. The throughline of the replies was: by design. The hooks issue was "posture, not a vulnerability." The detection bypass was "a heuristic limitation, not a boundary crossing."
I'll be careful about what I'm claiming. The policy texts and their dates are public git β not in dispute. That my reports were filed before the rewrite and closed after it is from my own records.
Their best case (it's better than you'd think)
When I pushed back on the closures, the maintainers didn't stonewall β they had a real argument for why none of this counts as a vulnerability, and it's worth hearing. Their point: you can never catch every dangerous command just by matching it against a list of known-bad text β there are endless ways to write the same command, so this kind of check will always miss some. That's a built-in limit, not a fixable bug. So, they argue, the check was never meant to be the real protection; the real protection is running the whole AI inside a locked-down box (a "sandbox"), so even if it's tricked, the damage can't escape.
And it's a fair point. The maintainers were polite, took the report seriously, and even asked for help improving things β this wasn't a brush-off. You could even say their first policy oversold that check by calling it a "core security boundary" at all, and that changing the wording just set the record straight.
So why didn't it sit right?
"Just run it in a sandbox" misses the point
Their whole defense leans on one move: just run the agent in a sandbox β a locked-down container β and it won't matter what slips past the gate. As someone about to trust this with confidential customer data, that's exactly where it fell apart for me.
A container protects the host machine. It does nothing to protect what you actually care about, because the data you're trying to keep safe lives inside the container β the conversation history, the customer records the assistant is working with, the API keys in its environment. An attacker who lands code execution inside the agent is already in the room with all of it. "We sandboxed the blast radius" is cold comfort when the blast radius contains your customers' data.
And these agents aren't hermetic toys. Hermes, like its peers, is built to be hosted and reached remotely β a web app and messaging gateways (Telegram, Discord, and more) so you can talk to it from anywhere. People put them on public servers. That is exactly the deployment where untrusted input meets sensitive data and real privileges. "Run it isolated from hostile input" is hard advice to follow when taking input from the outside world is the entire product.
The one bug they actually fixed
There's a detail the "it's all by design" framing can't quite absorb.
Of the three findings, the LLM-judge flaw is the one they fixed β quietly, in code, weeks later, with no advisory, no CVE, and no credit. The two they sent written closures for were the other two, both waved off as "by design." The one they fixed is the one they never tried to call working-as-intended β because it wasn't a structural limit, it was an implementation bug.
You don't harden a guard you believe was fine. The code history says someone agreed it was a real flaw; the paper trail says nothing at all. To be precise: the commit is public β nothing was hidden. The fair criticism is narrower and harder to wave off: a genuine flaw was fixed without acknowledgment, while the ones they answered were dismissed.
This isn't a Hermes problem. It's an everyone problem.
This is what turned a private frustration into something I think is worth publishing. Hermes is not an outlier. Every AI agent is drawing the safety boundary in a different place, and right now each one grades its own homework.
Look at the same stretch of 2026:
Anthropic's Claude Code had a closely related issue β repository configuration, including hooks, executing commands around the trust dialog. Same class as my startup-code finding. Anthropic made the opposite call: a real vulnerability, fixed, with a stronger consent dialog and a credited CVE-2025β59536.
Cursor had CVE-2026β22708: an allowlist turned into the attacker's friend via environment-variable poisoning.
And a steady drip of agent-framework RCEs that Microsoft itself has documented.
Same underlying question β is "a control that can be bypassed" a vulnerability, or expected behavior inside the trust envelope? β and every project answers differently, sometimes case by case. One project's credited CVE is another's "working as designed." A researcher who finds the identical bug gets a thank-you here and a closed-as-out-of-scope there. That inconsistency is bad for everyone: users can't reason about what's actually protected, and researchers can't predict whether good-faith work will be welcomed or waved off.
Who gets to move the line?
I went looking for a tool I could trust with confidential data. What I found instead was a question the industry is answering project by project, with no agreement and sometimes mid-disclosure: in an AI agent, where does the security boundary actually go β and who gets to move it?
Until we answer that out loud, "it's secure" means something different for every agent you deploy. And you'll only find out which definition you got after you've handed it your data.
Disclosure note: these findings were reported privately. One was fixed (uncredited); two were closed as out-of-scope under a policy revised after submission, and reflect documented, intentional design positions the maintainers stand behind. Nothing here is a working exploit β the load-bearing claims are public git commits, a public policy diff, and the maintainers' own written responses. The point was never the payloads. It was the process β and the question.