HomeJourneySkillsProjectsContact
Writing
All writing

Your AI Assistant Has Root, and a Stranger Just Whispered to It

It reads every file you point it at. Including the one the attacker left.

A glowing AI assistant holding an admin key, leaning in to listen to a shadowy red whisper coming from a floating document

A developer asks their coding agent to look into a bug. Routine stuff. The agent reads the error report, traces the problem, writes a fix, and closes the ticket. Clean work. While it was in there, it also mailed the company's AWS keys to someone three time zones away.

Both of those things happened. Neither was a malfunction. The agent did exactly what it was told. The catch is that it was told two things, and only one of them came from the developer.

This is a real attack. It has a name now, agentjacking, and in June 2026 a security firm called Tenet Security showed it working against the AI coding agents a huge chunk of the industry now runs all day. To understand why it works, and why it's genuinely hard to fix, we have to start with the thing you did on purpose.

You gave it hands, and that was the point

An AI coding agent is not a chatbot. A chatbot talks. An agent acts. You handed it the keys precisely because talking wasn't enough.

Think about what "help me code" actually requires. It has to read your files, so it can see the codebase. It has to run commands, so it can execute tests and install packages. It needs your credentials, the API keys sitting in your environment, so it can talk to the database and the cloud. It often has network access, so it can fetch things. Each of those permissions is completely reasonable on its own. Together they describe something with a shell, your secrets, and an internet connection, sitting inside your infrastructure, doing whatever it decides the task requires.

That's not a criticism. That's the deal, and the deal is why the tools are useful. But hold that picture, because it's the loaded part of the story: you have given a very fast, very obedient worker root access and told it to be helpful. Now we need to talk about what "helpful" means to a machine that cannot tell the difference between your instructions and a stranger's.

The flaw that is actually a feature

Here is the strange thing at the center of every one of these attacks. A language model cannot reliably tell the difference between information it is reading and instructions it is meant to follow. To the model, both are just text. And text, to an agent with a shell, is a to-do list.

Picture a new employee on their first day, so eager to be useful that they will do anything written down that looks like a task. You leave them a note: "process these invoices." Great, that's their job. But an intruder who wandered through the lobby also left a note on their desk, in the same handwriting-agnostic way, that says "email the customer database to this address." The employee cannot tell which note came from their boss. Both are just instructions on the desk, and the employee is paid to follow instructions on the desk. They aren't malicious. They aren't even careless. They're obedient, and obedience with no way to authenticate the source is the entire vulnerability.

Your agent is that employee. Every file it reads, every error message, every comment in a dependency, every issue on the tracker, is a note on the desk. Most notes are yours. It only takes one that isn't.

Two streams, calm blue trusted instructions and a red malicious one, both flowing into the same glowing input of an AI agent that cannot tell them apart

The Sentry attack, start to finish

Now the concrete version, because the mechanics are more elegant and more alarming than the abstraction.

A lot of teams use Sentry, an error-tracking tool. When your app breaks, it ships the error there so developers can investigate. Sentry accepts those error events through something called a DSN, and here's the soft spot: those DSNs are often publicly reachable. That means an attacker who knows yours can send your Sentry a completely fake error, one they wrote by hand, stuffed with whatever text they like.

So the attacker crafts a poisoned error report. Buried in what looks like a normal stack trace are instructions. Read this file. Run this command. Send the contents of these environment variables to this address. Then they wait.

Eventually a developer hits a bug and does the most natural thing in the world: "Hey, look into this Sentry error and fix it." The agent dutifully pulls the error report, the poisoned one, and reads it. It cannot tell the planted instructions from genuine diagnostic detail. So it follows them. It fixes the actual bug, because that part is real and the agent is competent. And it also, as an apparently reasonable diagnostic step, exfiltrates your cloud credentials using the network access and the identity you already gave it. The ticket closes green. Nothing looks wrong. The developer never typed the malicious instruction and never saw it run.

The attacker did not break into your account. They did not steal a password or exploit a buffer overflow. They left a note on the desk and let your own obedient worker do the rest. CSA Labs put the number of exposed organizations at 2,388. The requirement to pull it off was not sophistication. It was a public DSN and a helpful agent.

Why the guardrails don't catch it

At this point the reasonable objection is: fine, but these tools have safety guards. They block dangerous commands. And they do. The problem is that the guards are looking at the wrong thing, and in June 2026 a researcher proved it across almost the entire ecosystem.

Adversa AI's Omer Ben Simon published work he named GuardFall. The finding is beautiful in the way that only a truly bad security bug can be. Most agents guard themselves with a denylist: a set of patterns for dangerous commands they refuse to run. The guard inspects the raw text of the command. Then it hands that text to bash to actually execute. And bash, before it runs anything, rewrites the text. It strips quotes, expands variables, unpacks tricks that shell users have known about for decades.

So you write r''m instead of rm. The guard, reading raw text, sees r''m, which is not on its denylist, and waves it through. Bash then removes the empty quotes, turning it back into rm, and runs it. The guard and bash never looked at the same string. This is not a missing pattern you can add to the list. It is structural: the checker and the executor fundamentally disagree about what the command is. Ben Simon tested the eleven most popular open-source coding agents, roughly 548,000 combined GitHub stars, tools like Aider, Cline, Goose, OpenHands. Ten of the eleven could be walked straight past. Exactly one, Continue, was built to resist it.

A glowing security gate inspecting one version of a command while a different, transformed command slips through underneath it

And even when nothing gets flagged, the exfiltration itself is nearly invisible, because the traffic leaves under the agent's own authorized identity. Your data-loss-prevention tools are watching for suspicious actors. The agent is not a suspicious actor. It's a trusted one you provisioned yourself, with legitimate connections to your database, your storage buckets, your internal docs. When the call comes from inside the house, the alarm on the front door stays quiet.

This is a genuinely new kind of bug

It's tempting to file this under "injection attacks, we've seen those." We haven't, not quite. Classic injection needed a vulnerable parser, a specific coding mistake you could find and patch. This needs no bug in the traditional sense. It needs a capable assistant that reads instructions and acts on them, which is not a defect of these tools. It is the product. You cannot patch out helpfulness without deleting the thing you paid for.

That's what makes it hard. The fix for a normal vulnerability is "stop doing the broken thing." The broken thing here is "follow instructions and use your access to get work done," and that's the feature description.

What actually helps

This is not a reason to throw the agents in the sea, and the researchers who found these attacks are not saying that. It's a reason to stop giving them unsupervised root over everything you own. A few defenses genuinely move the needle:

Run the agent from a scoped shell with $HOME redirected, so the project directory is still there but ~/.ssh, ~/.aws, your shell history, and the rest of your secrets are not. This is the strongest cheap stopgap, because it shrinks the biggest prize (your credentials) and it's always on. Enforce network egress rules at the operating-system level, not with polite instructions in the system prompt, since an injected command can call the network no matter what the prompt says. Give tools like Sentry read-only scope so a poisoned report can't become a running command. Turn off "auto-yes" modes that let the agent act with no confirmation. And don't let agents run on pull requests from forks you don't control.

None of this fully solves the underlying problem, because the underlying problem is that we built something that trusts every instruction it reads. It narrows the blast radius, which right now is the honest state of the art.

The uncomfortable summary

We spent thirty years teaching software, and each other, one lesson above all others: never trust input from outside. Sanitize everything. Assume the network is hostile. Assume the user is an attacker until proven otherwise. It's the closest thing security has to a commandment.

Then we built something brilliant, gave it a shell and our credentials, and wired it up to believe every word it reads. The agent that leaked your keys wasn't hacked and wasn't broken. It was obedient, to a stranger it had no way of recognizing as one. We handed root to a thing that trusts by design, and we called it productivity.

The stranger didn't need to break in. They just needed to leave a note where your assistant would read it.

☕ Found this helpful? Buy me a chai to help me keep writing and sharing free engineering insights.