What happened
Claude Code lets you connect it to remote tools like Slack, GitHub, or a database through MCP, short for Model Context Protocol. It’s the standard way an AI coding agent reaches outside its own chat window to read from, or act on, another service. You run claude mcp login, approve access in your browser, and Claude Code can then use that service on your behalf.
Anthropic’s documentation describes what happens to the login token that connection creates in one line: “Authentication tokens are stored securely and refreshed automatically.”
Domen Kožar tested Claude Code 2.1.257 on Linux and published what he found. After connecting Claude Code to a few MCP servers, he opened the file where it keeps its login, ~/.claude/.credentials.json, and found a plain, readable block for each connected server, including the access token itself.
Anthropic’s own credential-management documentation confirms this is expected behavior, not a bug: on Linux, that file is protected only by standard file permissions set to mode 0600, restricting ordinary file access to your user account. Nothing in the file is encrypted.
Windows works the same way, protected only by your Windows user account’s normal file permissions. macOS uses the encrypted Keychain, with a file fallback when the Keychain rejects a write, such as when it is locked during an SSH session.
That gap between “stored securely” and what’s actually happening matters, because file permissions and encryption protect against different things. A permission of 0600 stops other user accounts on the same machine from reading the file. It does nothing if something is already running as you: a malicious package pulled in when you install a JavaScript project’s dependencies, a compromised code editor extension, or any other process running with your own account’s access. Any of those can open that file directly and read the token in plain text, no cracking required.
Why this matters for you
On Linux and Windows, OAuth-authenticated MCP connections leave plaintext credentials for the connected services. If you’ve connected Claude Code to your GitHub account, a Slack workspace, a database, or a cloud provider’s dashboard, the token that lets Claude Code act as you in that service is sitting on disk in a form any process running as your user can read.
This isn’t a newly discovered break-in. Nobody has to defeat encryption to get at it, because Linux and Windows never put encryption in front of it in the first place. The risk shows up the moment something else on your machine, not Claude Code, gets to run code as you: a bad dependency, a malicious VS Code extension, or any other compromise of your own account. Stored tokens can then be read by a process with the same file access.
What builders should do next
Treat every MCP connection as a standing credential, not a one-time login, and manage it that way.
Run /mcp inside Claude Code to see every server you’re currently authenticated to. For any server you’re not actively using right now, choose “Clear authentication” from that menu, or run claude mcp logout <name> from your terminal. Either option clears that server’s stored credentials. If a token may already have been stolen, revoke the service authorization as well; removing your local copy does not invalidate someone else’s copy.
For servers you do keep connected, narrow what the token can actually do. Claude Code lets you set the permissions, called scopes, it requests during login, by setting oauth.scopes in your MCP server config. For a Slack connection, this example requests channel-reading, messaging, and search permissions. It does not select particular channels:
{
"mcpServers": {
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"oauth": {
"scopes": "channels:read chat:write search:read"
}
}
}
}
Check the permissions actually granted by the provider. Narrow scopes reduce what a stolen token can do. Claude Code may also request offline_access for token refresh when the authorization server advertises it.
On macOS, check whether the login went into the Keychain or the fallback file. SSH, a remote terminal connection, can leave the Keychain locked, but it does not by itself establish where the credential was stored.
Delegation and storage need separate controls
OAuth lets you approve delegated access in a browser and renew it without copying keys by hand. It does not encrypt the stored token. Keep only the connections you need, narrow their permissions, and protect the account that can read their credentials.
End of article