Watercooler5 hours ago

The Claude Code Exploit Split Two Threads on What Prompt Injection Even Means

A researcher reported 60 to 80 percent success executing code through Claude Code Opus 5 in auto mode. Hacker News spent 116 comments failing to agree it was prompt injection, and Lobsters settled it in 24.

The WJS Desk

Sep 2, 2026 · updated 2 hours ago · 7 min read

Photo by Daniel Trylski on Pexels

On 26 August a researcher writing as wunderwuzzi published a chain that ends with Claude Code Opus 5 executing attacker-supplied code on the host machine. Reported success was 60 to 80 percent across three variants, on samples of five runs each. Five days later the writeup reached the Hacker News front page and collected 377 points and 116 comments, while a parallel thread on Lobsters drew 23 points and 24 comments.

We read both threads end to end expecting a fight about Anthropic. We got a fight about vocabulary, and the two communities finished in different places. Then we ran the underlying mechanism ourselves, because the thing both threads kept circling turned out to be a single Python flag.

What the writeup claims, and what Anthropic said back

The context is a marketing number. Per the writeup, Anthropic's Boris Cherny posted a chart showing 0.00 percent attack success for Opus 5 in auto mode, drawn from a Trajectory Labs evaluation of 72 indirect prompt injection scenarios run ten times each. Auto mode became the Claude Code default in mid-August. wunderwuzzi's chain was not in that scenario set.

The chain pushes Claude off WebFetch and onto curl with an HTTP 415 response, serves a zip of encoded records, then relies on a habit rather than a jailbreak. Claude declines to run the attacker's binary, which is the safe call. It then writes its own Python decoder and runs it inside the directory it just unpacked, where a file named struct.py waits to shadow the standard library module of the same name.

VariantReported successSample
python3 -I -c C2 chain3/55 runs
claude -p subprocess, recon3/55 runs
claude -p subprocess, writes plus launch4/55 runs

Those are the author's numbers on five runs per variant, not ours. We did not reproduce the full chain and we are not presenting it as our measurement. The writeup reports that Anthropic closed the disclosure as "Informative" and described auto mode as "a convenience feature backed by a best-effort classifier, not a security guarantee", pointing at OS isolation and network egress control as the actual boundary.

The argument, stated fairly on both sides

One camp says the label is wrong and the label matters. Prompt injection means content getting treated as instructions. Here the website never issued an instruction Claude obeyed: Claude was told to summarise a page and wrote insecure code to do it. Calling that prompt injection makes the term mean any security incident that happens near a model.

The other camp says the label is a distraction from the claim it is measured against. Anthropic used a 0.00 percent injection figure as the public reason auto mode could be the default. If a plain web address ends in remote code execution most of the time, the reassurance fails whether or not the mechanism fits a taxonomy.

The takes

"I would not have thought to call this prompt injection, and I'm wondering what other people think. What I understand by prompt injection is a specific vulnerability where instructions in the content are misinterpreted as being either user instructions or system prompts."

That is hyperpape on Lobsters, at 5 points, opening the thread's most productive exchange.

"But Anthropic themselves are the ones who made the equivalence of '0.00% prompt injection attack success rate == auto-mode is safe'."

ipython on Hacker News, making the strongest version of the opposing case.

"What's interesting to me about this is that it targets Claude's specific tics. Everyone gets the same model, so by learning the model's behavioral patterns you can target it better."

colinmarc on Hacker News. This is the observation we have not seen made elsewhere: a monoculture of one model is a monoculture of one exploitable habit.

"I don't think it's related to the auto mode at all. It would work perfectly in the manual mode. It does not even need Claude: just give a human a similar archive and hope they run some simple Python from the directory at least once."

yeputons on Hacker News, and this is the sharpest dissent in either thread.

"The point is that auto mode gives people a false sense of security that leads them to believe they don't need to run Claude in a proper sandbox. This same attack running in a sandbox (even in YOLO mode) would be comparatively harmless."

kevsim on Hacker News, answering yeputons directly.

"Yeah my takeaway after reading the article was this seems more like a demonstrated vulnerability in Python than in Claude Code."

DangitBobby on Hacker News, whose claim we went and tested.

"So far the only useful mode I have found is just 'allow everything and go to lunch'. And it doesn't feel like I'm holding it right, but here we are."

alkonaut on Hacker News, describing what most people reading this actually do.

Where the two platforms parted company

Hacker News never resolved the definitional question. It forked, and the larger fork became a practical thread about sandboxing an agent on a laptop you also work on. mjmvisser reported moving to a VS Code dev container in about 30 minutes. silversmith asked the harder question, which is how to sandbox on a Mac while still letting the agent drive a browser for OAuth and visual checks.

Lobsters, with a fifth of the comments, converged. hyperpape's objection held up under pressure, simonw argued the other side, and then wrote: "Huh, I think you're right about this." He went on to separate this case from an attack he does consider prompt injection, where a README tells the agent to run a command that turns out to be a malicious package. hyperpape then proposed a name for the new thing: import hijacking.

A 24-comment discussion produced a working term and a public change of mind. A 116-comment discussion produced a survey of container setups.

We ran the mechanism, and the fix is one flag

DangitBobby's point deserved a test. We made a directory holding a struct.py that prints a marker, plus a decoder that does nothing but import base64, which pulls in struct underneath. Then we ran it the ways an agent would.

mkdir shadowtest && cd shadowtest
printf 'print("[shadow] local struct.py imported")\n' > struct.py
printf 'import base64\nprint(base64.b64encode(b"hi"))\n' > decode.py

python3 decode.py                  # shadowed
python3 -c "import base64"         # shadowed
python3 -I decode.py               # clean
PYTHONSAFEPATH=1 python3 decode.py # clean on 3.11+
InvocationPython 3.9.6Python 3.12.14
python3 decode.pyshadowedshadowed
python3 -c "import base64"shadowedshadowed
python3 -Icleanclean
python3 -Pflag does not existclean
PYTHONSAFEPATH=1ignoredclean

Two things fell out of that. python3 -c, which colinmarc called a load-bearing tool for this model, puts the empty string at the front of sys.path, so the working directory wins. And the 3.9.6 column is the Python that ships with the macOS command line tools, where -P does not exist and PYTHONSAFEPATH is ignored, so the mitigation most people would reach for silently does nothing.

The detail that reframes it: the writeup notes the attacker's own payload runs python3 -I so it does not fall for the same trap it just set. The attacker applies the fix. Claude applies it only sometimes, which the author lists among the cases where the attack failed.

The comment nobody upvoted

On Lobsters, Wilfred asked the obvious question: why was curl needed at all, when a file fetched by WebFetch would also need decoding. darichey answered it at 2 points. The WebFetch tool filters and summarises content server side, so the zip never reaches the client machine. That single reply explains why the first stage of the chain exists, and it is the most useful sentence in either thread.

Our read

hyperpape is right on the vocabulary and it does not rescue the marketing. This is import hijacking, aimed at a model whose habits are public because everyone runs the same one. The 0.00 percent figure was still offered as the reason a permissive default was safe, and that is a claim about outcomes rather than taxonomies.

What bothers us more is the advice both threads landed on. Everyone said to sandbox it, so we read the sandbox documentation. Claude Code's built-in Bash sandbox is off by default. When it cannot start because a dependency is missing or the platform is unsupported, the documented behaviour is to warn and run the command unsandboxed unless you set sandbox.failIfUnavailable to true. Its default read policy covers the whole computer, and the docs say this "still allows reading credential files such as ~/.aws/credentials and ~/.ssh/". There is also an escape hatch where Claude may retry a blocked command with dangerouslyDisableSandbox, and in auto mode the approver for that retry is the classifier this research just walked through.

The sandbox everyone recommended defaults to failing open, reads your SSH keys, and hands the exit door back to the classifier under discussion.

If you take one action from this, set "allowUnsandboxedCommands": false and sandbox.failIfUnavailable to true, and configure sandbox.credentials so a compromised command cannot read the keys it would exfiltrate. Then export PYTHONSAFEPATH=1 and check with python3 -VV that the interpreter your agent reaches for is new enough for that to mean anything.

What would change our mind: a reproduction against a session with strict sandbox mode and a narrow domain allowlist. If it still lands, the argument about definitions was never the interesting part.

Share

Two threads read the same Claude Code exploit. HN argued for 116 comments. Lobsters settled it in 24 and named it: import hijacking. We tested the mechanism. #ClaudeCode #AppSec #Python #PromptInjection

Never miss a ship

The best stuff that shipped this week, delivered every Thursday. Free, no spam. We read all the boring stuff so you get the fun parts.

Keep reading