I submitted a security report to Anthropic after Claude Code exposed my .NET User Secrets in its model context. They classified it as “Informative – Working as Designed.”

“Working as designed” is a triage label, not a verdict. But taken at face value, it points to something architectural: security is enforced tool by tool, not around the agent as a whole, and certainly not at the OS-boundary level.

1. The original issue: .NET User Secrets end up in the model context

.NET developers commonly use dotnet user-secrets to keep development credentials in their user profile, outside the project tree.

These secrets can include:

• API keys

• Database connection strings

• Passwords

• Third-party service credentials

• Other sensitive application configuration

Consider this scenario:

  1. You have a .NET application.

  2. You have configured User Secrets.

  3. You launch Claude Code in your project directory.

  4. You ask Claude to inspect your application configuration.

Claude can execute:

dotnet user-secrets list

And/or read the plaintext secrets.json file.

%APPDATA%\Microsoft\UserSecrets\<id>\secrets.json

Because tool output is returned to Claude, those credentials become part of the conversation context. This is not a vulnerability in .NET. It is a consequence of giving an AI coding agent access to a developer’s local environment.

2. Anthropic’s response: Working as designed

Anthropic explained to me that Claude Code executes commands with the privileges of the developer’s user account. Their position is that commands such as dotnet user-secrets list require approval in the default permission mode. They also pointed to four security mechanisms:

• Permission prompts

• Deny rules

• Hooks

• Optional sandboxing

Fair enough: an agentic tool has to execute commands. Allowlisting dotnet* is on me. But there’s a second problem underneath. secrets.json is unencrypted, so to the agent it’s just another readable file. In any case, their response made me look closely at what those mechanisms actually protect.

3. Command rules are not security boundaries

Suppose I configure a deny rule:

{
"permissions": {
"deny": ["Bash(dotnet user-secrets list*)"]
}
}

Now Claude cannot execute the obvious command directly. But what happens if I ask Claude:

“Write a Bash script that inspects my .NET User Secrets configuration and execute it.”

Claude could create:

#!/bin/bash
dotnet user-secrets list

And then execute:

bash inspect-secrets.sh

The rule matches the command string, not what the script does. The same applies to Python, PowerShell, compiled executables and any other indirect execution path. PreToolUse hooks can inspect tool calls, but they cannot reliably interpret every script or execution path.

Manual approval doesn’t solve this either. The developer approves running the code, but approval does not limit what the code can reach. Blocking a command is not the same as restricting access to the data that command retrieves.

4. The sandbox only covers shell commands

I then looked at Anthropic’s official sandbox documentation:

https://code.claude.com/docs/en/sandbox-environments

Anthropic offers several sandboxing approaches, and they cover different things. Out of the box, sandboxing is off. You have to enable it first. Once enabled, Bash, PowerShell and Monitor tool commands and their child processes are restricted. Claude’s file tools, MCP servers and hooks run outside it. File tools are gated only by permission rules.

Consider the different execution paths:

Sandbox-bash is not a comprehensive isolation boundary around Claude Code. Granted, the sandbox runtime srt claude wraps the whole Claude Code process, including file tools, MCP servers and hooks. It is a beta research preview and does not run on native Windows.

5. Native Windows?

On Windows, you need a container or virtual machine to get a sandbox. But here it gets tricky. WSL2 gets dicey fast. By default, WSL2 mounts Windows drives under /mnt, for example:

/mnt/c/Users/yourname/
/mnt/c/Users/yourname/AppData/

Microsoft documents that Linux processes accessing Windows files run with the permissions of the Windows user who launched WSL. On its own, that leaves your Windows profile readable from inside WSL2. Claude will still happily read your secrets, directly or through a tool, and expose them in its context.

Docker is a substantially better option. But the core problem remains the same: a container is only as isolated as its configuration. The difference is that Docker adds a boundary between Claude Code and your Windows host. Unlike WSL2, where your Linux environment can access Windows files through /mnt/c, a properly configured Docker container only sees the files, directories and resources you explicitly expose to it… nah snap… it means that Claude Read still has access to your User Secrets as you need them to launch your app.

Windows has filesystem ACLs, restricted tokens, AppContainer isolation, Job Objects and other process isolation mechanisms. This is not an argument that Windows lacks the necessary security primitives. It is a product limitation: Claude Code’s built-in sandbox does not support native Windows.

6. The bigger problem: malicious data exfiltration through MCP and other tools

So far this has been accidental exposure: Claude runs a command and the credentials land in its context. Now consider deliberate exfiltration.

What happens when an agent has access to both sensitive local data and external tools?

Claude Code supports MCP integrations that can connect the agent to external services and systems. Depending on the integrations configured, these might include:

• GitHub repositories

• Issue trackers

• Project management systems

• Databases

• Internal APIs

• Cloud services

• External HTTP services

Now imagine an agent that can read local credentials and also call an MCP server that can send data out. The attack chain is short:

  1. An agent gains access to a local credential or sensitive configuration file.

  2. The credential enters the agent’s context or becomes available to an integration.

  3. The agent invokes an external tool or MCP server.

  4. Sensitive information is transmitted outside the developer’s environment.

A prompt injection could trigger it: malicious instructions in a repository, a compromised dependency, tampered documentation or any other untrusted content the agent reads.

Malicious MCP servers are not far-fetched. A rogue Postmark MCP package has already been found secretly BCC’ing an attacker on outgoing email.1 This is not some exotic theoretical attack; it is a baked-in supply-chain problem.

This is not a claim that every MCP server can access every local file, or that every Claude Code integration automatically permits arbitrary exfiltration. The point is architectural: an agent’s security depends on the combined privileges of all its tools, not just the sandbox around its shell.

7. What to do now: move secrets out of plaintext

The upshot: don’t use User Secrets on a machine where an agent runs. Until agents operate inside a real OS-enforced boundary, stop keeping secrets where an agent can trivially read them.

  1. Use a proper secrets manager. Options include self-hosted Infisical, 1Password (op run), Bitwarden Secrets Manager, or Azure Key Vault for teams already in Azure. A local Infisical instance gives you encryption at rest, access control and audit logs without leaving your machine.
  2. Inject secrets at process start, not from disk. Tools like infisical run -- dotnet run or op run -- dotnet run pass secrets to your app as environment variables, so nothing sits in a plaintext file.
  3. Keep the vault out of the agent’s reach. If Claude can run the vault CLI in an already-authenticated session, you’ve moved the problem rather than solved it. Require interactive unlock or biometric approval, and launch your app from a terminal outside the agent session.
  4. Use development-only, scoped, rotatable credentials. Assume anything the agent can touch may eventually leak, and limit the blast radius accordingly.

This is a workaround, not a fix. The real fix is the one I’d still like to see: a consistent, OS-enforced boundary around the whole agent, with native Windows support, shared filesystem policy across all tools, process-tree and MCP isolation, and network egress controls. Until then, don’t leave plaintext secrets lying around next to an agent.

1
https://postmarkapp.com/blog/information-regarding-malicious-postmark-mcp-package