Christian Lehnert — Linux, Hacking & Faith

Your Agent Has Your Keys

Christian Lehnert2026-09-12~8 min read

Your Agent Has Your Keys

People install a coding agent the way they install a linter. Run the
command, approve a prompt or two, get back to work. Claude Code, Codex,
Cursor, whatever the team standardised on, it lands on the work laptop
in five minutes and starts being useful immediately. That speed is the
problem, because almost nobody stops in those five minutes to ask the
one question that matters: what can this thing actually reach, and what
happens when something turns it against me.

The honest answer is that a coding agent runs with your privileges. It
can read your files, run shell commands, reach your network, and use
the credentials sitting in your environment, because that is exactly
what makes it useful. The agent is not sandboxed from your work. It is
your work, with a language model deciding what to do next. And in 2026
we have a growing pile of documented cases where that decision was made
by someone other than you.

What the Agent Can Actually Do

Strip away the chat interface and a coding agent is a process on your
machine with three capabilities that matter: it reads (your source, your
files, your environment variables), it executes (shell commands, tools,
whatever you wired up), and it talks to the network (the model API, and
increasingly a stack of external tools). Simon Willison named the
dangerous combination the lethal trifecta: private data, untrusted
content, and the ability to communicate externally. Put all three in one
process and prompt injection stops being a curiosity and becomes data
exfiltration.

The agent has the first and third by design. The second, untrusted
content, is the one people do not see coming, because they think of the
agent as reading only what they typed. It is not. It reads the files in
the repo, the output of the tools it calls, the issue it was asked to
triage, the web page it fetched, the error report it pulled. All of that
is input to the model, and the model does not reliably distinguish "data
I was asked to look at" from "instructions I should follow." That gap is
the whole attack surface.

The Config Files Are an Attack Surface

Here is the part almost nobody thinks about when they clone a repo and
point their agent at it: the agent reads configuration out of the
project, and that configuration can do things.

Claude Code is configured through JSON files in the project, .claude/ settings.json and .mcp.json. These are convenient. They are also code
execution waiting to happen if they arrive from someone else. In
February 2026, Check Point Research disclosed CVE-2025-59536, and it is
worth understanding exactly because it is so mundane. A malicious
repository could plant hook configuration in .claude/settings.json
that ran arbitrary shell commands at agent initialisation, before the
trust dialog ever appeared on screen. Open the repo, and the attacker's
command already ran. The same research showed .mcp.json could be set
to auto-approve all MCP servers, so opening the project silently
launched attacker-controlled tools. A related issue let a project set
ANTHROPIC_BASE_URL to an attacker's endpoint, routing your API traffic,
tokens included, to them before you were told anything.

Sit with that. The mechanism is not an exploit in the usual sense. It is
the agent doing exactly what its config file told it to, where the config
file came from a repository you cloned and trusted. The JSON that
configures your agent is executable trust, and you inherit whatever is in
the project you opened. A pull request that adds a .claude/settings.json
is a pull request that can run code on the machine of every reviewer who
opens it with an agent.

Injection Through Tools You Chose

It gets more uncomfortable, because the untrusted content does not have
to be a file you can see. It can come through a tool you deliberately
connected and have every reason to trust.

In June 2026, Tenet Security published what they called agentjacking. The
setup: a developer connects the Sentry MCP server so their agent can read
error reports, a completely reasonable thing to want. An attacker files a
crash report with a plausible-looking resolution section that contains a
shell command. The developer asks the agent to clear the unresolved
errors. The agent reads the malicious report alongside the real ones,
treats the embedded text as instruction, and runs the command. Tenet
found over two thousand organisations with injectable Sentry endpoints
and an 85% execution rate across Claude Code, Cursor, and Codex in their
testing.

Look at what is missing from that attack. No stolen credential, because
the endpoint that accepts crash reports is public by design. No
compromised dependency, no phishing, no malware. The injection arrives
through a service the developer chose, reviewed, and trusts, riding in as
ordinary tool output. This is the lethal trifecta firing exactly as
predicted: the agent has your data, it read untrusted content, and it can
act. The toolchain itself became the attack surface the moment the model
started treating tool output as trusted context.

Why This Is Worse Than a Normal Dependency

A malicious npm package runs with the privileges of your build. A
compromised coding agent runs with the privileges of you, interactively,
while you watch and approve, having been socially engineered through
content the model could not tell apart from your instructions. The blast
radius is everything you can reach: the repos on the laptop, the cloud
credentials in your environment, the internal services on the VPN, the
secrets in the files the agent can read. Same shape as the non-human
identity problem I have written about, except the identity is you, and
the thing wielding it is improvising.

And the reflex most people have, click approve on the tool-use prompt, is
precisely the wrong instinct, because the prompts arrive constantly and
approving them is how you get work done. The permission dialog becomes a
TOFU prompt: a security control trained into a reflex, clicked through by
everyone, catching nothing.

What To Actually Do

You do not need to stop using agents. You need to stop running them as if
they were trusted the way a linter is. In rough order of effort and
payoff:

Treat every repository config as untrusted code. Before you point an
agent at a cloned project, look for .claude/settings.json, .mcp.json,
and their equivalents, the same way you would glance at a Makefile before
running make. A config file from someone else's repo is something you
are choosing to execute.

Give the agent its own credentials, never your good ones. Do not let it
inherit the cloud keys and tokens sitting in your shell. Scope it a
dedicated, minimal identity, and keep the secrets that matter out of the
files and environment it can read. If it never had the production key, it
cannot leak the production key.

Pin and review your MCP servers and skills. Each one is code and each one
is a channel for injected tool output. Pin versions, read the source of
community servers before you connect them, and grant each the least it
needs, especially network access.

Put the whole thing in a box for anything serious. This is where my
tank-os-with-llms setup comes in: a hardened container that runs Claude
Code and Gemini CLI behind a default-deny egress firewall, as an
unprivileged user, with only a bind-mounted workspace exposed and the
corporate network, the cloud metadata endpoint, and the host's loopback
all unreachable. The point of that setup is exactly this threat model. If
the agent gets hijacked, the iptables perimeter and the unprivileged user
are what stand between one bad tool-output and your whole network. The
container does not stop the injection. It bounds what the injection can
reach, which is the only thing that reliably works.

The Point

A coding agent is not a tool you run, it is a capability you delegate, and
you delegate it your files, your network, and your keys the moment you
install it. The documented attacks of 2026 are not exotic: a JSON config
in a cloned repo that runs commands before you see a dialog, a crash
report that carries a shell command through a tool you trust. None of them
needed to break anything, because the agent was already holding
everything, waiting for someone to tell it what to do.

Install the agent, by all means. But look at the config files in the
repos you open, give it credentials you can afford to lose, review the
tools you connect, and put a real boundary around it for anything that
touches production. The speed of setup is the trap. The five minutes you
saved not thinking about this is the five minutes an attacker is counting
on.

Tagged:
#security #ai-agents #claude-code #codex #mcp #prompt-injection
← Back to posts