DEV Community

Neeraj Kumar Singh Beshane
Neeraj Kumar Singh Beshane

Posted on Originally published at linkedin.com

The Approve Button Is Not Evidence

He wrote his court filing in white ink.

Humans saw a normal document. Software saw instructions to rule in his favor.

On August 6, a Connecticut judge sanctioned him — even though nothing was fooled.

I can't stop thinking about why that ruling feels so obviously right.

Matthew Elliott was representing himself against a healthcare provider. He set three-point white text on a white background inside two court filings, and court staff only caught it because the whitespace looked strange.

Connecticut's courts don't use AI on filings. Judge Walter Spader sanctioned him anyway. His reasoning: a model takes the operator's instructions and the file's contents as one undivided stream, so a document built to read differently to a machine than to a person is defective on arrival.

The document is defective the day it is filed, whether or not the trick lands.

I'm telling you this because the same trick is sitting in your terminal, and last week it got three CVE numbers.

A document that says one thing to a human and another to a machine is a forged document.

The approval dialog in your agent stack is that same document.

It took three separate disclosures in one week to convince me how deep this goes.

The catalog said read-only. It wrote to disk

Start with the concrete one. On August 18, NVD published CVE-2026-75913 at severity 9.3 against CodeWhale, a terminal coding agent. Its git_show tool takes a revision string from the model and drops it into a real git invocation with no separator in front of it, so git keeps reading flags out of that value.

Hand it a revision of --output=/home/you/.ssh/authorized_keys and your read becomes a write, because git show honors the flag.

What turns this into something worth an issue is how the tool describes itself. It's registered as auto-approved, so no prompt ever appears.

It's also declared read-only, which is what the model is told and what any reviewer skimming the registry believes. The one moment where a human could have objected was removed by a declaration that turned out to be false.

NOT ACCEPTABLE

// flaw 1: never prompts
// flaw 2: declared ReadOnly - untrue
// flaw 3: no sentinel, no dash check

fn approval_requirement(&self) -> ApprovalRequirement {
    ApprovalRequirement::Auto
}

args.push(rev.to_string());
Enter fullscreen mode Exit fullscreen mode

ACCEPTABLE

// approval derived from reach, not declared by hand
fn approval_requirement(&self) -> ApprovalRequirement {
    ApprovalRequirement::Prompt
}

// reject flag-shaped values
if rev.starts_with('-') {
    return Err(ToolError::invalid_input(
        "rev must not start with '-'"))
}

// git stops parsing flags after this sentinel
args.push("--end-of-options".into());
args.push(rev.to_string());
Enter fullscreen mode Exit fullscreen mode

The sentinel is the fix, shipped in 0.8.64. It was missing from a tool whose entire safety story was a self-description nobody re-tested.

The two-line fix is not the story. The story is why nobody knew it was missing.

What you see is what you sign

There's a name for the property being violated here, and it's older than most of the people shipping agent frameworks.

In 1998 Peter Landrock and Torben Pedersen coined WYSIWYS — what you see is what you sign — for the rule that a signature only means something if it binds the exact thing the signer was shown.

They were writing about digital signatures on documents. But an approval prompt is a signature ceremony too, and nearly every agent architecture leans on it as the last human boundary while almost none provide the property the whole ceremony depends on.

Once you look through that lens, the week's other two disclosures stop being separate stories.

CodeWhale's second CVE, CVE-2026-75858, published the same day, is the engine's version of the same failure. Its rlm_eval tool runs model-supplied Python in a real interpreter, and its approval requirement returns automatic — which the engine reads as never prompt, without ever consulting the operator's configured policy.

If you set your approval policy to strict, that setting is not overridden. It is never read.

And then there's the case where the prompt actually fired. On August 14, Straiker's STAR Labs published research in which a single email, disguised as a backup request, reached an agent connected to Google's Antigravity.

Asking for zip and curl directly would have produced approval prompts naming every SSH key and the destination host. So the injected instructions had the agent stage the work into a script first.

Email — script — one benign approval showing a filename — keys gone.

The dialog told the truth about the filename and lied by omission about everything else. No patch fixes that one, because the dialog text came from the same model the attacker had already reached.

Three systems in one week. In every case the human was holding a receipt that did not describe the transaction.

The pitch on my own desk

Then, while I was drafting this exact issue, someone ran the trick on me.

A pitch landed in my inbox: an AI had found bugs humans missed for years, three CVEs attached as receipts. I nearly ran it as this issue's opening story. Then I checked the receipts, which is the whole point of this issue.

Two resolve immediately. CVE-2026-5888 is real uninitialized memory in Chrome's WebCodecs, and Chrome's release notes credit it to the Octane Security Team by name: Giovanni Vignone, Paolo Gentry, Robert van Eijk. CVE-2026-60161 is a real VirtualBox flaw that Oracle's July advisory credits to the same organization. Both check out.

The third identifier returns record-not-found at MITRE. One bad receipt out of three.

What I found when I read past the pitch is more interesting than the pitch. Octane published their own case study on the Chrome finding, and it does not describe a machine working alone. A researcher picked the attack surface, chose the vulnerability classes worth hunting, tightened the scope as noisy results came back, then wrote the proof of concept himself and confirmed the leaked bytes were heap pointers under a debugger. Their words: an instrument under expert direction rather than a black-box report generator. Seventy-two hours, not one pass.

A pitch is an approval dialog too: a summary written by an interested party, waiting for your click.

I audited mine. Most people approve.

Run the Signature Audit

Here is the ten-minute version of that discipline, run against your own agent instead of my inbox. It extends the tool-registry review you already do when onboarding.

  1. Which tools never ask? — list every auto-approved tool.

  2. Which of those claim read-only? — intersect the two lists:

rg -l "ApprovalRequirement::Auto" | xargs rg -l "ReadOnly|read_only"
Enter fullscreen mode Exit fullscreen mode

(spelled auto_approve in other frameworks)

  1. Can any argument name a destination? — a path, a URL, a revision.

  2. Does the dialog match what ran? — approve one action that touches a file and a host, then read your own logs, not the agent's summary of itself.

You end up with a receipt worth keeping: three probe results, plus one count — tools that are both auto-approved and declared harmless.

Zero is the only passing value.

New here? Securing the Agentic Stack follows the trust boundaries that appear when software can turn what it reads into action.

Next week I want the layer under this one: whether an audit log can prove which policy version was in force when an action ran.

Spader sanctioned a document that fooled no one — because the defect is in the document, not the damage.

An auto-approved tool that calls itself read-only is that same document, sitting in a registry you own.

Nobody has sanctioned yours yet.

Which record would fail first in your stack — the tool catalog, the engine's policy check, or the dialog text?

  • Neeraj

Top comments (0)