New Attack Hijacks Developer Machines via Claude Code and Innocent Repositories
Independent researcher 0Din published a genuinely clever piece of security work — not because the primitives are new, but because the chain is. An attacker hides a reverse shell three hops away from anything Claude Code actually reads: an error message, a setup script, a DNS TXT record. None of those three pieces, examined alone, looks malicious. Together, they hand the agent's shell to whoever controls the domain. That is worth understanding properly.
For a developer who runs Claude Code against cloned repos as part of a daily workflow, the uncomfortable fact is this: the repo does not have to be malicious. The instructions do not have to be malicious. The error message does not have to be malicious. The attack lives in the sequence — the same sequence a reasonable agent is built to follow when installation fails.
The core insight: the attack exploits the gap between what Claude Code reads (an error message containing a suggested fix) and what it actually executes (a base64-decoded command fetched live from DNS). Three indirection steps, none of which the agent was built to scrutinize, sit between trusting an error and spawning a shell. Closing that gap is the durable fix — and it is not specific to Claude Code.
How the chain actually works
The researcher's disclosure describes a setup with three components, none of which looks alarming on its own — and SecurityWeek's coverage confirms the full sequence:
- A normal-looking repository. Setup notes that tell Claude Code to install a Python package during first-time setup. The notes are instructions, not exploits.
- A recoverable error. The package throws an error if it has been used before initialization. The error message suggests an init command — exactly the kind of suggestion an agent is trained to act on when an install fails.
- A setup script. Running init calls this script. The script pulls a config value from a DNS TXT record, then executes it as a shell command.
The DNS value is base64-encoded, so a reverse-shell signature never appears in plaintext anywhere on disk or on the wire. The repository holds no payload. The error message holds no payload. The payload lives in a DNS record the developer never reads, and it can be changed at any time.
Once the interactive shell opens, every credential, API key, token, and secret on the machine is exfiltratable. The attacker can also deploy a backdoor for persistence after the shell closes.
Distribution is the easy part. The attacker posts the repo link in a job listing, a tutorial, a Discord channel. Every developer who clones it and asks Claude Code to get it running gets hit.
Why this is harder to catch than a typical supply-chain attack
Traditional supply-chain attacks smuggle malicious code into the package. This one smuggles malicious behavior into the recovery flow. A code scanner reading the repo finds a setup script that reads a config value — boring, common, looks like a hundred legitimate bootstrappers. The malicious payload is fetched live at execution time and never written to disk in plaintext.
The researchers frame it as indirect prompt injection: the reverse shell sits three indirection steps away from anything the agent actually evaluated — an error message it trusted, a script that fetched a value, and a DNS record it never saw. That is the trust gap. The agent's job is to follow instructions and recover from errors. The attack turns that job description into the vulnerability.
It also generalizes. Any agent that reads error messages and acts on them, runs setup scripts from cloned repositories, and has unconstrained network egress to resolve DNS has the same attack surface. The mechanism is Claude Code-specific today. The shape is not. If you maintain agent-readable repos, our agent-readable repository structure guide shows how to constrain what agents consume in the first place.
11 production screens. Login, database, payments — all wired.
The SaaS Dashboard Kit ships everything already connected. Nothing to set up. Live demo at saas.otf-kit.dev.
Hardening that actually closes the gap
Five concrete steps, each cheap to take today:
1. Sandboxed shell, not the host shell. Run the agent inside a container or VM with no access to your real ~/.ssh, ~/.aws, ~/.npmrc, or browser keychain. The reverse shell still opens — but it opens inside a disposable environment. A sketch of the shape:
docker run --rm -it \
--network=none \
-v $(pwd):/work \
-w /work \
node:20-slim \
bash--network=none kills the DNS TXT fetch. That is the whole payload gone. If the agent needs network for real work, use an explicit egress allowlist rather than blanket access.
2. Read the error message yourself. When an install fails and the agent proposes running an init command, say no, read the message, and decide. The 0Din attack works because agents are trained to recover automatically. Train yourself not to.
3. Audit setup scripts before running. Every bootstrap script in a cloned repo should be reviewed before the agent sees it. One file, one read, one decision. If it reads from DNS or hits a URL you do not control, that is a red flag, not a configuration step. Our AI app security checklist covers this class of review.
4. DNS logging and egress controls. If you operate a developer fleet, log TXT-record queries. Base64-encoded responses to setup-script invocations are a strong signal. Even simpler: block outbound DNS for build environments that do not need it.
5. Treat error messages as untrusted input. An error message that says run X to fix me is data, not instructions. This is the conceptual fix, and it applies to every agent, not just Claude Code. The 0Din attack is a textbook case of prompt injection via a side channel — the agent's own error stream. Environment rules like the ones in Cursor rules that actually work are one place to encode this posture.
None of these are exotic. All five can be in place by end of week. The combination — sandboxed shell, reviewed bootstrap scripts, network restrictions, and a habit of reading errors — turns a real attack into a non-event.
What this means for the wider agent ecosystem
This will not be the last chain of this shape. The pattern — trusted local context fetches untrusted remote context, then executes it as instructions — is exactly what agents are built to do. As long as that pipeline exists, someone will find a way to abuse it.
The defense cannot be to be smarter about reading error messages. The agent will read them, because that is the job. The defense has to live underneath the agent — in the environment it is given, the network it can reach, the secrets it can touch.
Industry-wide, that means default-deny egress for agent runtimes as a default, not a recommendation; signed or pinned bootstrap scripts, where a setup script pulling from DNS at runtime is a red flag in any toolchain review; and reviewed-by-convention scaffolds, where repositories whose setup is generated, validated, and pinned do not need an agent to improvise — and an agent that cannot improvise past an error message is safer than one that can.
Neither published write-up cited here confirms a vendor-side fix for this chain, so do not assume one exists. Operate as though the class is open.
The durable layer underneath
This is where a structured starting point earns its keep. An agent working from a known template — one with a pre-validated package.json, pinned dependencies, an explicit setup script you have already audited — does not need to read an error message and guess. It runs the scaffold you already approved. When installation fails, recovery is constrained to the same surface, not improvised from whatever the error stream suggests.
That is not a Claude Code replacement. Disclosures like this are how the tooling gets safer. The layer that does not change when the model changes, when the agent changes, when a new indirection trick lands: a deterministic scaffold the agent operates inside. The 0Din chain works because the agent had to make decisions about a setup it had never seen. The defense is to give it a setup it does not have to decide about.
Reverse shells three hops from a trusted error message are clever. The fix is not cleverer AI. It is less improvisation, more convention, and a shell the agent cannot reach your secrets from.
Start from scaffolds you have already audited at OTF templates — full-stack kits your AI coding agent can actually ship to production.
Sources
- Clone this repo and I own your machine — 0Din research — researcher primary; source for the three-hop chain, the base64-DNS exfiltration detail, and the indirect-prompt-injection framing.
- New attack abuses Claude Code and harmless-looking repositories — SecurityWeek — press corroboration of the full chain sequence.
Ship the product, not the setup.
- 11 production screens — auth, billing, team, analytics, settings
- Real database, payments, and login — all wired on day 1
- AI configs pre-tuned so your agent extends instead of regenerates