Your AI coding assistant is leaking secrets
May 12, 2026
AI desktop assistants and coding tools need credentials to reach external services, and many of them store those credentials as plaintext JSON at predictable paths in the user's home directory. This research covers how credential storage works across 14 popular AI tools, where OS keychain integration is present or missing, and eight attack scenarios that turn that exposure into real risk, from malware-based theft to remote session hijacking to supply-chain compromise via MCP servers.
How Claude, Copilot, Cursor, and other AI tools store credentials in plaintext and 8 examples of how attackers exploit them
The problem
AI desktop applications need to authenticate with external services. Claude Code needs your OAuth tokens. GitHub Copilot needs your GitHub auth. Continue.dev needs your API keys. MCP servers need tokens for Azure DevOps, Slack, databases, and everything else you've connected. Where do all these credentials go? Mostly into plaintext JSON files in your home directory. These files are in well-known or predictable locations, making them easy to find with read access to a system.
What I found
I explored 14 popular AI tools (see reference at the end of the blog) across Windows, macOS, and Linux. These are the things that stuck out to me the most.
Claude Code CLI
~/.claude/.credentials.json contains your OAuth access and refresh tokens in plaintext JSON:
{
"claudeAi": {
"type": "oauth",
"access": "sk-ant-oat01-...",
"refresh": "sk-ant-ort01-...",
"expires": 1776098433694
}
}
On Linux, the file is created with 0600 permissions (owner-only read/write). On macOS, credentials go to the Keychain. But on WSL, the Windows-side file inherits the mount's default 0777 permissions making your Claude OAuth tokens world-readable to any process on the system. The refresh token is the really dangerous one here. It's long-lived and can generate new access tokens indefinitely. An attacker who obtains it has persistent access to your Claude account until you explicitly revoke it.
MCP server configurations: the aggregation problem
Model Context Protocol (MCP) servers let AI assistants connect to external tools. Each connection needs authentication, and those tokens typically end up in a single config file like this:
{
"mcpServers": {
"github": { "env": { "GITHUB_TOKEN": "ghp_realToken..." } },
"azure": { "env": { "ADO_MCP_AUTH_TOKEN": "eyJ0eX..." } },
"slack": { "env": { "SLACK_BOT_TOKEN": "xoxb-..." } },
"database": { "env": { "DB_PASSWORD": "prod_password" } }
}
}
One file. Multiple services. One read operation can compromise them all. Trend Micro found that 48% of 19,402 MCP server implementations recommend plaintext credential storage.
Continue.dev: API keys in plaintext
Continue.dev stores every configured API key directly in ~/.continue/config.json:
{
"models": [{
"provider": "anthropic",
"apiKey": "sk-ant-api03-YOUR-ACTUAL-KEY"
}]
}
The community acknowledges this as a problem (GitHub issue #1729). Environment variable substitution is supported (${VAR_NAME}) but isn't the default behavior.
Cline: credentials synced to the cloud
Cline's MCP settings live in an unencrypted JSON file within VS Code's globalStorage. The problem is VS Code Settings Sync automatically uploads this file to GitHub. If you have Settings Sync enabled, your MCP credentials are sitting in GitHub's cloud.
The VS Code SecretStorage confusion
GitHub Copilot, Cline, and other VS Code extensions use the SecretStorage API, which encrypts secrets in a SQLite database (state.vscdb) using AES-128-CBC. This sounds secure until you realize:
- VS Code extensions run without sandboxing
- The encryption key sits in the OS keychain, accessible by any user-level process
- Any malicious extension can read other extensions' secrets
- The extension identification system is vulnerable to spoofing
The encryption provides defense against offline disk access but not against any process running as the same user.
Attack surface examples
I identified 8 real-world attack scenarios I wanted to point out enabled by AI credential exposure.
1. Credential theft via malware
The file paths are predictable and consistent across installations:
~/.claude/.credentials.json
~/.continue/config.json
~/.aws/credentials
~/.config/gcloud/application_default_credentials.json
~/Library/Application Support/Claude/claude_desktop_config.json
~/.claude.json
Infostealer malware already targets browser cookies, SSH keys, and cloud credentials. Adding a handful of AI tool paths to the target list is trivial. No privilege escalation required; standard user-level file read is sufficient.
A single malware infection could yield Claude OAuth tokens, all API keys in Continue.dev, every MCP server token, and AWS credentials. The paths are the same on every installation of every tool.
Risk: CRITICAL. High likelihood, high impact.
2. Hijacking a Claude Code remote control session
This is the scenario that should scare you. Claude Code has a Remote Control feature (claude remote-control) that lets users control their local Claude Code session from a phone, tablet, or browser via claude.ai/code. All code execution stays on the local machine. The remote device is just a control interface.
Here's the problem: the remote connection doesn't require re-authentication. Once a session is active, anyone with the session URL can send instructions. And all those instructions are executed locally on the developer's machine.
Now combine that with --dangerously-skip-permissions.
This flag disables all interactive permission prompts. File writes, shell commands, network requests, MCP tool calls, everything executes automatically without asking the user. It's intended for isolated CI/CD containers, but sometimes users use it on their workstations for convenience. It can also be set as a persistent default in settings.json via "defaultMode": "bypassPermissions".
The attack chain:
- Attacker steals OAuth tokens from
~/.claude/.credentials.json(via malware, SSRF, or any file-read vulnerability) - Tokens are portable so they work from any machine
- If the victim has an active Remote Control session, the attacker connects and takes over
- If the victim runs with
--dangerously-skip-permissions, the attacker now has unrestricted shell access as the victim's user:- Read/write any file on the system
- Execute arbitrary commands (
curl,ssh,docker, package managers, etc.) - Install backdoors, exfiltrate data, pivot to other machines
- Access SSH keys, cloud credentials, and every other secret on the system
- Modify git repos, CI/CD pipelines, and deployment configs
Even without --dangerously-skip-permissions, Claude Code in acceptEdits mode auto-approves file edits and common filesystem commands. This can still be dangerous. The permission model was designed to protect against accidental actions, not against a malicious actor controlling the session.
Risk: CRITICAL (with --dangerously-skip-permissions), HIGH (default permissions).
3. Lateral movement via Claude OAuth tokens
An attacker who obtains a Claude OAuth refresh token from ~/.claude/.credentials.json can:
- Generate new access tokens remotely (access tokens expire in ~60 minutes, but the refresh token is long-lived)
- Access the victim's Claude conversations and workspace files
- Use any MCP servers the victim has configured (accessing their GitHub repos, Azure DevOps projects, Slack workspaces, and databases through the AI assistant as a proxy)
The tokens are portable. Copy the credentials file to another machine, and Claude Code will use it. Anthropic implements refresh token rotation, so using a stolen token may eventually invalidate the original, but the initial use succeeds and the attacker may gain access before rotation kicks in.
Risk: HIGH. Medium-high likelihood, high impact.
4. MCP token aggregation: lateral movement
A single MCP config file aggregates tokens for multiple external services. For example, one file could yield:
GITHUB_PERSONAL_ACCESS_TOKEN→ code repos, PRs, CI/CDADO_MCP_AUTH_TOKEN→ Azure DevOps projectsSLACK_BOT_TOKEN→ internal Slack workspace- Database passwords → production data
JIRA_API_TOKEN→ project management, internal tickets
Unlike distributed credential storage where compromising one channel exposes only a subset of credentials, MCP's aggregation pattern means a single file disclosure cascades to compromise all connected services.
Risk: CRITICAL. High likelihood, high impact.
5. Malicious VS Code extension: credential exfiltration
VS Code extensions run without sandboxing. All extensions share the same process permissions. A malicious or compromised extension can:
- Access the
state.vscdbSQLite database directly - Retrieve the encryption key from the OS keychain (accessible by any user-level process)
- Decrypt all extension secrets: Copilot tokens, Cline API keys, MCP credentials
Cline's cline_mcp_settings.json doesn't even need decryption. It's unencrypted plaintext in VS Code's globalStorage, and it gets synced to the cloud via Settings Sync.
The package.json publisher and name fields that identify extensions are vulnerable to spoofing, making it possible to impersonate legitimate extensions.
Risk: HIGH. Medium likelihood, high impact.
6. WSL permission escalation
Developers using WSL get hit from both sides. Windows-installed AI tools store credentials under C:\Users\<you>\, which is mounted in WSL as /mnt/c/Users/<you>/ with 0777 permissions by default. The same credential file that's NTFS-protected on the Windows side is world-readable from the Linux side.
In multi-user WSL environments or compromised containers, this is easy to exploit. Any process running on the WSL system can read Claude OAuth tokens, MCP configs, etc., stored on the Windows side.
Risk: HIGH for WSL users. High likelihood, medium-high impact.
7. .mcp.json committed to git: credential exfiltration
Claude Code's .mcp.json at the repo root is designed to be version-controlled so teams can share MCP server configurations. If a developer includes inline tokens instead of env var references:
- Tokens appear in git history
- Even after removal,
git log -p .mcp.jsonreveals them - Automated scanners (TruffleHog, GitLeaks, etc.) can find them at scale across GitHub/GitLab
Anthropic and GitHub's secret scanning partnership catches some exposed API keys, but MCP config tokens for other services (Azure DevOps, Slack, databases) are not covered by automated scanning. There's no GitHub secret scanner pattern for ADO_MCP_AUTH_TOKEN or SLACK_BOT_TOKEN embedded in JSON env blocks.
Risk: MEDIUM. Medium likelihood, medium-high impact.
8. Supply chain attack via MCP servers
MCP servers are often npm packages. The supply chain risk is the same as any npm dependency, but with a critical difference: MCP servers receive credentials at startup.
- Popular MCP server package on npm is compromised (or a typosquat is published)
- Users configure it in their
claude_desktop_config.jsonwith real tokens in theenvblock - The MCP server process has access to all environment variables passed to it, including tokens
- Compromised server exfiltrates tokens to attacker's infrastructure
Without proper OAuth 2.1 audience validation (RFC 8707), a malicious MCP server could also receive access tokens and replay them against other services (token passthrough attack).
The 48% plaintext credential statistic means nearly half of all MCP server setups hand credentials directly to the server process on launch. If that server process is compromised, every user who installed it is compromised too.
Risk: MEDIUM. Low-medium likelihood, high impact.
Bonus: CI/CD token theft
The claude setup-token command generates a one-year OAuth token (CLAUDE_CODE_OAUTH_TOKEN) for CI/CD pipelines. This creates a unique risk:
- The token works from any machine for up to a year
- CI/CD systems often have weak secrets management and limited job isolation
- Build logs may accidentally expose environment variable values
- A compromised CI/CD runner yields long-lived access to Claude with whatever permissions the pipeline runs
If your CI/CD pipeline runs Claude Code with --dangerously-skip-permissions (as many do for automation), a stolen CLAUDE_CODE_OAUTH_TOKEN grants unrestricted shell execution on any machine where the token is used.
Risk: HIGH. Medium likelihood, high impact.
What needs to change
For users (right now)
- Run AIHound. Know what's exposed on your machine.
- Fix permissions:
chmod 600on credential files. - Never use
**--dangerously-skip-permissions**on machines with real credentials or network access. If you need it, use it inside an isolated container with no mounted secrets. - Use env var references in MCP configs instead of inline tokens:
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
- Rotate tokens that have been in world-readable files or git history.
- Disable VS Code Settings Sync if you use Cline with MCP servers.
- Treat
**CLAUDE_CODE_OAUTH_TOKEN**like a root password. Rotate it regularly, never put it in build logs, and scope CI/CD permissions to the minimum necessary. - Add
**.mcp.json**to**.gitignore**if it contains inline secrets.
For tool builders
- Use OS keychains. macOS Keychain, Windows Credential Manager, and Linux libsecret exist for exactly this purpose. Never store credentials with plaintext JSON.
- Create files with
**0600**permissions. Not0644or0777. - Warn users when you detect inline secrets in MCP configurations.
- Don't sync credentials to the cloud through settings sync mechanisms.
- Implement OAuth 2.1 with proper token audience validation for remote MCP servers.
- Require re-authentication for Remote Control sessions. A session URL should not be a bearer token for arbitrary code execution.
- Audit MCP server packages before allowing installation, and support server allowlisting.
For the ecosystem
The OWASP MCP Top 10 lists "Token Mismanagement and Secret Exposure" as MCP01-2025. Anthropic and GitHub's partnership for automatic API key detection on GitHub is a great start, but it only covers Anthropic keys in public repos. MCP tokens for Azure DevOps, Slack, databases, and other services have no equivalent protection.
We need:
- Secret scanning that covers MCP configuration patterns, not just API key formats
- Credential helpers for MCP (similar to git credential helpers) that retrieve tokens from secure storage at runtime
- Mandatory OS keychain integration as the default
- Sandboxing for VS Code extensions
- Token-scoped Remote Control - Remote sessions should require their own authentication, not inherit the local session's full capabilities
The bottom line
The AI tooling ecosystem moved fast to ship features and left credential security as a bit of an afterthought. Almost half of MCP servers store credentials in plaintext. AI assistants keep OAuth tokens in JSON files on disk. Remote Control features let those tokens become remote code execution. And --dangerously-skip-permissions turns a stolen credential into full shell access on someone else's machine. The more tools you connect, the greater your risk becomes. A lot of AI credentials are not stored securely, so be sure to implement best practices for credential storage. Tools like AIHound can help you find these plaintext credentials on your systems.
AI desktop application credential storage locations for reference
This reference catalogs every credential location of some of the most popular AI desktop applications, coding assistants, and CLI tools.
Claude Code CLI
Developer: Anthropic Auth method: OAuth 2.0 (Claude.ai subscription) or API key
Credential files
Platform | Path | Format | Encryption | Contents |
|---|---|---|---|---|
|
Linux |
|
JSON
|
Plaintext (mode 0600) |
OAuth access/refresh tokens, multi-provider auth |
|
macOS |
Keychain: |
Keychain |
OS Keychain (encrypted) |
OAuth access/refresh tokens |
|
Windows |
|
JSON
|
Plaintext (NTFS ACLs) |
OAuth access/refresh tokens |
|
WSL |
Both Linux path AND |
JSON
|
Plaintext (often 0777 via mount) |
Same as above |
Credential file structure
{
"claudeAi": {
"type": "oauth",
"access": "sk-ant-oat01-...",
"refresh": "sk-ant-ort01-...",
"expires": 1776098433694
}
}
Every OAuth connection stores its own entry. The file contains credentials for Claude.ai, Claude API, Azure Auth, Bedrock Auth, and Vertex Auth depending on what the user has configured.
Key finding: On WSL, the Windows-side credential file inherits the mount's default permissions (0777), making it world-readable, which is a CRITICAL risk that doesn't exist on native Linux where the file is created with 0600.
Configuration files with potential secrets
Path | Contents |
|---|---|
|
|
Global MCP server configurations (may contain inline tokens) |
|
|
Project-scoped MCP server configs |
|
|
User preferences and permissions |
Authentication precedence order
Claude Code checks credentials in this order (first match wins):
- Cloud provider env vars (
CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX,CLAUDE_CODE_USE_FOUNDRY) ANTHROPIC_AUTH_TOKENenvironment variableANTHROPIC_API_KEYenvironment variableapiKeyHelperscript output (for dynamic/rotating credentials)CLAUDE_CODE_OAUTH_TOKENenvironment variable (long-lived, fromclaude setup-token)- OAuth credentials from
~/.claude/.credentials.jsonor Keychain
Known bug
A documented bug (GitHub issue #36779) shows that OAuth credentials are not properly persisted to macOS Keychain. Only the mcpOAuth field is stored while the primary auth token is missing, forcing re-authentication in new sessions.
Claude Desktop
Developer: Anthropic Auth method: Claude.ai session (Keychain-backed on macOS)
Configuration files
Platform | Path | Format | Encryption |
|---|---|---|---|
|
macOS |
|
JSON |
Plaintext (often 0644) |
|
Windows |
|
JSON
|
Plaintext |
|
Linux |
|
JSON
|
Plaintext |
MSIX virtualization issue (Windows)
On Windows, the MSIX installer creates filesystem virtualization. The "Edit Config" button opens %APPDATA%\Claude\claude_desktop_config.json, but the application may actually read from a virtualized path inside the MSIX container. This means:
- Users may edit the wrong file
- MCP server configurations are silently ignored
- No error messages indicate the problem
Pre-MSIX installations are grandfathered and read from the real AppData path.
What's in the config
The config file primarily holds MCP server definitions:
{
"mcpServers": {
"azure-devops": {
"command": "npx",
"args": ["-y", "@anthropic/azure-devops-mcp"],
"env": {
"ADO_MCP_AUTH_TOKEN": "actual-token-here"
}
}
}
}
The env block frequently contains plaintext tokens for external services.
GitHub Copilot
Developer: GitHub / Microsoft Auth method: GitHub OAuth
Credential storage
Platform | Location | Format | Encryption |
|---|---|---|---|
|
macOS |
Keychain: |
Keychain |
OS Keychain |
|
Windows |
Credential Manager |
Credential Manager |
DPAPI |
|
Linux (with libsecret) |
GNOME Keyring / KWallet |
libsecret |
OS-level |
|
Linux (no libsecret) |
|
JSON |
Plaintext (fallback) |
VS Code extension storage
Platform | Path |
|---|---|
|
Linux |
|
|
macOS |
|
|
Windows |
|
The state.vscdb file is a SQLite database encrypted with Electron's safeStorage API (AES-128-CBC). However, security research has shown this is vulnerable to malicious VS Code extensions. Any extension can access other extensions' secrets due to lack of sandboxing.
The encryption key is stored in the OS keychain (Code Safe Storage on macOS), accessible by any process with user permissions.
Token types
Prefix | Type | Supported |
|---|---|---|
|
|
OAuth token (default via |
Yes |
|
|
Fine-grained PAT (needs "Copilot Requests" permission) |
Yes |
|
|
GitHub App user-to-server token |
Yes (env var only) |
|
ghp_ |
Classic PAT
|
Not supported |
GitHub CLI auth (also used by Copilot)
Platform | Path | Format |
|---|---|---|
|
Linux |
|
YAML |
|
macOS |
|
YAML |
|
Windows |
|
YAML |
Contains oauth_token fields in plaintext YAML.
Cursor IDE
Developer: Anysphere Auth method: Cursor account + optional API keys
Storage locations
Platform | Paths |
|---|---|
|
macOS |
|
|
Windows |
|
|
Linux |
|
MCP configuration
~/.cursor/mcp.json, which follows the same mcpServers JSON structure as Claude Desktop. May contain inline auth tokens.
Known issues
Cursor stores conversation logs with world-readable permissions. These logs can contain credentials if users paste tokens into the chat interface.
Continue.dev
Developer: Continue (open source) Auth method: Direct API keys per provider
Configuration files
Platform | Path | Format | Encryption |
|---|---|---|---|
|
All |
|
JSON
|
Plaintext |
|
All |
|
YAML
|
Plaintext |
Credential format
{
"models": [
{
"title": "Claude 3.5 Sonnet",
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022",
"apiKey": "sk-ant-api03-ACTUAL-KEY-HERE"
}
]
}
All API keys are stored in plaintext at the user root. This is acknowledged by the Continue.dev community as a security concern (GitHub issue #1729).
Mitigation
Continue.dev supports environment variable substitution:
"apiKey": "${CONTINUE_ANTHROPIC_API_KEY}"
It checks .env files at the project root and custom locations specified via envFiles. However, the default behavior is plaintext if env vars aren't configured.
Cline (VS Code extension)
Developer: Saoud Rizwan Extension ID: saoudrizwan.claude-dev
MCP settings (plaintext)
Platform | Path |
|---|---|
|
macOS |
|
|
Windows |
|
|
Linux |
|
Critical: These files are plaintext JSON and are automatically synced to the cloud through VS Code Settings Sync. This means API keys and MCP credentials get uploaded to GitHub if sync is enabled.
API key storage
Cline stores API keys through VS Code's SecretStorage API (the same AES-128-CBC encrypted state.vscdb used by Copilot). Subject to the same malicious extension vulnerability.
Windsurf / Codeium
Developer: Codeium Auth method: Codeium account
Storage locations
Platform | Path |
|---|---|
|
All |
|
Look for config.json, auth.json, credentials.json within this directory.
MCP configuration
~/.codeium/windsurf/mcp_config.json with the same mcpServers structure.
Credential details are not well-documented publicly. Authentication appears to go through Codeium's centralized backend rather than local token storage in many cases.
ChatGPT Desktop
Developer: OpenAI Auth method: OpenAI account session
Storage locations
Platform | Path | Encryption |
|---|---|---|
|
macOS |
|
Keychain for session |
|
macOS |
|
Keychain for session |
|
Windows |
|
Credential Manager |
|
Windows |
|
Credential Manager |
ChatGPT Desktop primarily uses OS credential stores (Keychain on macOS, Credential Manager on Windows) for session tokens. JSON config files in the app data directory may also contain session data.
Amazon Q Developer / AWS
Developer: Amazon Web Services Auth method: IAM Identity Center / AWS Builder ID / IAM credentials
Credential files
Path | Format | Contents |
|---|---|---|
|
|
INI
|
Plaintext access key ID, secret access key, session token (per profile) |
|
|
INI |
Region, output format, SSO configuration |
|
|
JSON |
Plaintext SSO access tokens (cached) |
Credential file structure
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token = FwoGZXIvYXdzEBY...
Notes
- Amazon Q itself authenticates through IAM Identity Center or Builder ID, not through local file storage
- Default SSO session duration is 90 days (for setups created after April 2024)
- Static credentials in
~/.aws/credentialsare the primary risk. Consider using SSO/IAM Identity Center instead
Google Gemini CLI / GCloud
Developer: Google Auth method: Google account OAuth, API key, or service account
API key storage
Location | Format | Contents |
|---|---|---|
|
|
Environment variable |
Gemini API key |
|
|
Environment variable |
Google API key |
|
|
Dotenv |
API keys |
|
|
Dotenv |
API keys |
Application default credentials (ADC)
Platform | Path | Format |
|---|---|---|
|
Linux |
|
JSON |
|
macOS |
|
JSON |
|
macOS (alt) |
|
JSON |
|
Windows |
|
JSON |
ADC files contain client_secret, refresh_token, and potentially private_key (for service accounts) in plaintext JSON.
Authentication methods
Method | How | Local Storage |
|---|---|---|
|
Sign in with Google |
|
Cached locally for future sessions |
|
Gemini API Key |
|
Environment or |
|
Service Account |
|
JSON key file on disk |
|
ADC via gcloud |
|
|
|
Cloud Shell |
Automatic (metadata server) |
No local storage |
OpenClaw
Developer: OpenClaw (open source) Auth method: OAuth 2.0 per provider, API keys, channel-specific tokens
Overview
OpenClaw is a local-first AI agent platform that connects to 20+ messaging channels (WhatsApp, Telegram, Slack, Discord) and executes tools on the local machine. It stores credentials for both LLM providers and messaging channels.
Credential files
Path | Format | Encryption | Contents |
|---|---|---|---|
|
|
JSON
|
Plaintext (0600) |
OAuth access/refresh tokens + API keys per LLM provider |
|
|
JSON
|
Plaintext |
WhatsApp Baileys auth state |
|
|
JSON
|
Plaintext |
Legacy OAuth tokens (migration file) |
|
|
JSON |
Plaintext |
Channel pairing allowlists |
|
|
JSON
|
Plaintext |
Optional secrets payload for SecretRef resolution |
|
|
JSON5
|
Plaintext |
Main config with gateway auth token, channel tokens, agent API keys |
|
|
Dotenv
|
Plaintext |
Environment variable overrides (may contain API keys) |
Auth profile structure
Each agent has its own auth-profiles.json containing provider credentials:
{
"anthropic": {
"accessToken": "sk-ant-...",
"refreshToken": "sk-ant-ort01-...",
"expiresAt": 1776098433694
},
"openai": {
"apiKey": "sk-proj-..."
}
}
All tokens are stored in plaintext JSON by default. No OS keychain integration.
SecretRef system (opt-in)
OpenClaw supports an opt-in SecretRef system that replaces plaintext values with references to external sources:
Provider | Example | Description |
|---|---|---|
|
|
|
Reads from environment variable |
|
|
|
Reads from file (JSON pointer or single value) |
|
|
|
Runs vault-like executable |
Users must run openclaw secrets configure to scrub existing plaintext values and migrate to SecretRefs. The default behavior is plaintext storage.
Gateway authentication
The gateway uses a token for local access control:
{
"gateway": {
"auth": {
"mode": "token",
"token": "long-random-string-here"
}
}
}
This token can be a SecretRef but is commonly hardcoded in openclaw.json.
Known security issues
Issue | Severity | Details |
|---|---|---|
|
Plaintext credential storage |
HIGH |
OAuth tokens and API keys in
|
|
Agent tool bypass |
HIGH |
Agents with filesystem/exec tools can |
|
Tailscale exposure |
MEDIUM |
Remote access via Tailscale could expose the local gateway if token auth isn't configured
|
|
OAuth refresh failures |
MEDIUM |
Silent token refresh failures, Anthropic token truncation bugs
|
|
Session persistence |
LOW |
WhatsApp sessions not always persisted across restarts |
Credential locations summary
All files live under ~/.openclaw/ on all platforms (Linux, macOS, Windows). On WSL, both Linux-native and Windows-mounted paths should be checked.
MCP server configurations
Config file locations
Tool | Path | Scope |
|---|---|---|
|
Claude Desktop (macOS) |
|
Application |
|
Claude Desktop (Windows) |
|
Application |
|
Claude Code (local) |
|
User (private) |
|
Claude Code (project) |
|
Repository (shared) |
|
Cursor |
|
User |
|
VS Code |
|
Workspace |
|
Cline |
|
Extension |
Common MCP auth environment variables
Variable | Service |
|---|---|
|
|
Azure DevOps |
|
|
GitHub |
|
|
GitHub |
|
|
Slack |
|
|
Atlassian Jira |
|
|
Notion |
|
|
Linear |
Environment variables
The following environment variables are commonly set by users or tools and contain AI-related secrets:
Anthropic / Claude
Variable | Description |
|---|---|
|
|
Anthropic API key ( |
|
|
Bearer auth token |
|
|
Long-lived OAuth token (from |
OpenAI
Variable | Description |
|---|---|
|
|
OpenAI API key ( |
|
|
Organization identifier |
Variable | Description |
|---|---|
|
|
Gemini API key |
|
|
Google API key ( |
|
|
Path to service account JSON key file |
GitHub
Variable | Description |
|---|---|
|
|
GitHub token |
|
|
GitHub CLI token |
|
|
GitHub PAT |
|
|
Copilot-specific token |
AWS
Variable | Description |
|---|---|
|
|
AWS access key ( |
|
|
AWS secret key |
|
|
Temporary session token |
Azure
Variable | Description |
|---|---|
|
|
Azure DevOps MCP token |
|
|
Azure OpenAI key |
Other AI providers
Variable | Description |
|---|---|
|
|
Hugging Face |
|
|
Cohere |
|
|
Replicate |
|
|
Together AI |
|
|
Groq |
|
|
Mistral AI |
|
|
DeepSeek |
|
|
xAI / Grok |
|
|
Perplexity |
|
|
Fireworks AI |
Share on
Learn More
About the author
Darryl Baker
Senior Staff Security Researcher
Darryl G. Baker is a Senior Staff Security Researcher at Netwrix and a recognized authority in Identity and Active Directory security. With over a decade of identity systems experience, he has led enterprise security assessments, identity security trainings, and threat emulations focused on Active Directory, Entra ID, and Azure environments. Darryl has delivered highly rated trainings and demos at BlueTeamCon, BSidesCT, The Experts Conference, and Wild Wild West Hackin’ Fest. He’s the architect behind numerous hands on attack emulation labs—leveraging current red team and blue team tools to help defenders master everything from attack path analysis to threat hunting. In his sessions, Darryl blends deep technical insight with real world case studies, empowering blue team professionals to strengthen their identity security posture and defend against evolving adversary techniques.