Topic: Least agency
Your coding agent didn't get access. It got you
Coding agents run as the developer, with their cloud logins, Git tokens and SSH keys. Nobody granted that. A ten-minute audit to see what yours inherits.
In this post 7 sections
A developer opens a terminal and starts a coding agent. Nobody filled in an access request. Nobody decided which AWS account it could reach, which GitHub repositories it could push to, or whether it could read the SSH keys. It got all of that anyway, because it runs as the developer.
Microsoft says it plainly in its documentation for agent mode in VS Code: “Commands and tools run with your credentials.” That sentence is true of every local coding agent I looked at. They get access by inheritance, and the inheritance is bigger than most people assume.
Writes are fenced. Reads mostly aren’t
Every major coding agent ships some kind of boundary, and they share a pattern.
Writes outside the project are usually blocked or need approval by default. Reads are a different story. Claude Code’s sandbox is off by default, and its own documentation says that even when it’s on, sandboxed commands can read “most of the machine, including credential files such as ~/.ssh and ~/.aws/credentials”, with environment variables “inherited from Claude Code, including any secrets in its environment”. It adds: “There is no built-in credential deny list.” Cursor’s default setting means “the agent can read files outside the workspace without approval.” OpenAI’s Codex configuration reference keeps environment variables with KEY, SECRET or TOKEN in their names by default. Gemini CLI’s default macOS sandbox profile allows “broad file reads”.
Taking credentials needs reads. Reads are the boundary the defaults leave open.
The contrast is in the vendors’ own hosted products. In Claude Code’s cloud sessions, GitHub credentials “never enter the session VM”, which holds “a short-lived credential scoped to that session”. GitHub’s hosted Copilot agent can push to one branch, behind a firewall. When the vendors run the agent on their own infrastructure, they grant it narrow, short-lived access. On a laptop, it gets the developer.
The inheritance is your sessions, not just your files
The obvious list is the credential files: ~/.aws/credentials, ~/.config/gcloud, ~/.azure, ~/.kube/config, ~/.npmrc, ~/.pypirc, ~/.docker/config.json, ~/.git-credentials, ~/.ssh, every .env file in every project, and shell history. Several of these are plaintext by design. The Python packaging guide says .pypirc “stores your password in plain text”. Microsoft says the Azure CLI token cache is encrypted on Windows and kept in “plaintext files on Linux and macOS”.
The part people miss is that moving tokens into the operating system’s keychain doesn’t change what an agent can do. The tools that own those credentials will print them for any process running as you. gh auth token “outputs the authentication token”. aws configure export-credentials displays resolved AWS credentials. gcloud auth print-access-token and az account get-access-token do the same for Google Cloud and Azure. And a loaded SSH agent lets any process running as you use your keys without ever reading a key file.
So the real inventory is every login on the machine, and the question is which of those the agent should have at all.
Attackers have already made the list
When a malicious version of LiteLLM was published to PyPI in March 2026, the project’s own issue tracker listed what it collected: SSH keys and config, ~/.git-credentials, AWS credentials and config, the kubeconfig, Google Cloud application default credentials, the Azure directory, Docker config, .npmrc, .vault-token, .netrc, .pgpass, shell history, and the whole environment. That is the inventory above, almost path for path. The malware authors made the list most teams haven’t.
Coding agents have already been pulled into this. In the Nx “s1ngularity” compromise in August 2025, malicious package versions asked the developer’s own AI command-line tools to search the filesystem for secrets. Wiz reported the malware ran Claude, Gemini and Amazon Q with their permission-bypass flags (--dangerously-skip-permissions, --yolo, --trust-all-tools), and that about half the victims had at least one AI CLI installed. The AI step itself worked in under a quarter of cases, partly because the agents refused. The theft that mattered, gh auth token and .npmrc, was done by ordinary script code with the same inherited access. Wiz found almost 90 per cent of the leaked GitHub tokens still valid more than 24 hours after the repositories were taken down.
In June 2026, SafeDep documented the Miasma worm adding a .claude/settings.json and a .gemini/settings.json to repositories, each with a session-start hook that ran a credential stealer when the folder was opened in the agent. Cloning was harmless. Opening the repo in a coding agent ran the payload with everything the developer’s session could reach.
To be fair to the agents: I found no primary disclosure of a coding agent stealing a developer’s credentials on its own through prompt injection. The agent sits in the same blast radius as every install script it runs, and adds new ways in.
A ten-minute audit
This prints names and identities, never secret values. Don’t paste the output anywhere, and don’t add --show-token to gh auth status.
First, which credential files exist (macOS, Linux or Git Bash):
for p in .aws/credentials .aws/sso/cache .config/gcloud .azure .kube/config \
.config/gh/hosts.yml .git-credentials .npmrc .pypirc \
.docker/config.json .netrc .ssh; do
[ -e "$HOME/$p" ] && echo "FOUND ~/$p"
done
Then, who those credentials say you are:
aws sts get-caller-identity
gcloud auth list
az account show
kubectl config get-contexts
gh auth status
ssh-add -l
git config --global --get-all credential.helper
Then the names of secrets in your environment, and anything that bypasses your agent’s prompts:
env | grep -iE 'key|secret|token|passw' | cut -d= -f1
grep -rnE 'dangerously-skip-permissions|--yolo|trust-all-tools' ~/.bashrc ~/.zshrc 2>/dev/null
For each line of output, write down what it can reach, whether it expires, and whether the agent needs it. That list is the access your agent has today.
Shrinking it without buying anything
Most of the fix is configuration you already have:
- Swap long-lived AWS keys for IAM Identity Center logins. Sessions default to one hour, with a maximum of 12.
- Use fine-grained GitHub tokens limited to the repositories needed. GitHub says a classic token “can access every repository that you can access”.
- Load SSH keys with a lifetime and confirmation, using
ssh-add -tand-c. - Turn on the boundaries the agents ship. In Claude Code, enable the sandbox, add credential deny entries and set
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB. In Codex, stay off--yoloand stop KEY, SECRET and TOKEN variables reaching subprocesses. In Cursor, set read access to the workspace. In Gemini CLI, turn on Trusted Folders. - Run agents in a dev container or a separate OS user that doesn’t mount your home directory.
- Read a cloned repo’s
.claude,.gemini,.cursor,.vscodeand.mcp.jsonbefore opening it in an agent. Starting the agent runs them.
A deny rule written in a project instruction file isn’t a control. Claude Code’s own documentation notes that its read deny rules don’t apply to “arbitrary subprocesses that read or write files indirectly, like a Python or Node script”. The operating system boundary does the work.
From inheritance to grant
The fix the hosted products already use is the one to copy. The agent gets its own identity and only the access it was granted, through short-lived credentials it can’t print and hand on. Risky actions wait for a person, and every call is recorded against the agent that made it. I argued the general case in why your AI agent shouldn’t have your API keys, and least agency covers how far an agent should act before checking back.
That is how AgentValet works with Claude Code: the agent calls the platforms it needs through a broker that holds their credentials, so those credentials never sit in the developer’s shell. The Claude Code integration page shows the setup.
Sources
- VS Code, security considerations for AI and agents: code.visualstudio.com
- Claude Code, sandboxing: code.claude.com; permissions: code.claude.com; security: code.claude.com
- Cursor, run modes: cursor.com
- OpenAI Codex, configuration reference: learn.chatgpt.com
- Gemini CLI, sandboxing: geminicli.com; trusted folders: geminicli.com
- GitHub, Copilot cloud agent risks and mitigations: docs.github.com
- GitHub CLI, gh auth token: cli.github.com; AWS CLI, export-credentials: docs.aws.amazon.com
- Microsoft Learn, MSAL-based Azure CLI: learn.microsoft.com; Python Packaging User Guide, .pypirc: packaging.python.org
- LiteLLM issue 24512: github.com
- Nx security advisory GHSA-cxm3-wv7p-598c: github.com; Wiz, s1ngularity: wiz.io; Wiz, s1ngularity’s aftermath: wiz.io
- SafeDep, Miasma worm and AI coding agent config injection: safedep.io
- AWS IAM Identity Center, session duration: docs.aws.amazon.com; GitHub, managing personal access tokens: docs.github.com