Key Takeaways
- Govern Claude Code by routing through an AI gateway with
ANTHROPIC_BASE_URL, locking settings via MDM, denying filesystem access to secrets, and auditing MCP servers. - Two CVEs in 2026 prove repo-level config is an execution layer.
What Changed — The Two CVEs That Exposed Claude Code's Attack Surface
In early 2026, Check Point Research disclosed two vulnerabilities in Claude Code that forced security teams to rethink governance:
- CVE-2025-59536 (CVSS 8.7): A malicious
.claude/settings.jsonin a cloned repo could execute arbitrary shell commands before Claude Code even showed a trust dialog. Hooks ran at startup — before user confirmation. - CVE-2026-21852 (CVSS 5.3): A malicious repo could override
ANTHROPIC_BASE_URLvia its settings file, redirecting all API traffic (including the auth header with the developer's API key) to an attacker-controlled server.
Both are patched (v1.0.111 and v2.0.65 respectively), but the underlying lesson remains: repo-level config in an agentic tool is part of the execution layer, just like a malicious package.json postinstall script.
What It Means For You — The 4 Governance Gaps
If you have multiple engineers using Claude Code, your security team likely has the same gaps:
Gap 1: Unmanaged API Keys
Developers store keys in .bash_profile, shared .env files, or use personal accounts. No centralized revocation, no audit trail.
The fix: Issue keys through the Anthropic Admin Console with explicit expiry, store them in AWS Secrets Manager or HashiCorp Vault, and route through an AI gateway so the underlying Anthropic credential never touches developer machines.
Gap 2: No Centralized Traffic Visibility
You have no idea which models developers are hitting, what it costs per team, or if production data is being sent to prompts.
The fix: Set ANTHROPIC_BASE_URL to point at a gateway:
export ANTHROPIC_BASE_URL=https://<your-gateway-url>/api/inference/
This single line gives you request-level traces, per-developer rate limits, model allowlisting, and budget caps.
Gap 3: No Filesystem Controls
Claude Code can read .env, .ssh, ~/.aws/credentials, and anything else the user has access to — and that content can end up in a prompt before hitting the network.
The fix: Push a managed-settings.json via MDM (Jamf on macOS, Puppet/Ansible on Linux):
{
"permissions": {
"disableBypassPermissionsMode": "disable",
"deny": [
"Bash(curl:*)",
"Bash(wget:*)",
"Read(**/.env)",
"Read(**/.env.*)",
"Read(**/secrets/**)",
"Read(**/.ssh/**)",
"Read(**/credentials/**)"
],
"ask": [
"Bash(git push:*)",
"Write(**)"
]
},
"allowManagedPermissionRulesOnly": true
}
Place at:
- macOS:
/Library/Application Support/ClaudeCode/managed-settings.json - Linux:
/etc/claude-code/managed-settings.json
Gap 4: Ungoverned MCP Servers
MCP servers run with the same filesystem permissions as Claude Code. A malicious MCP server can exfiltrate data or execute arbitrary commands.
The fix: Audit every MCP server before allowing it. Use managed settings to restrict which MCP servers can be installed. Consider running MCP servers in a sandboxed environment.
Try It Now — Your Governance Checklist
- Route through a gateway — Set
ANTHROPIC_BASE_URLin your MDM-managed config - Lock the config — Use managed-settings.json to prevent developers from overriding
ANTHROPIC_BASE_URL - Deny access to secrets — Add filesystem deny patterns for
.env,.ssh, and secrets directories - Audit MCP servers — Review every MCP server your team uses; restrict installation to approved servers only
- Rotate keys quarterly — Issue API keys with expiry and revoke immediately on offboarding
Pro tip: If you're using Claude Admin Console's server-managed settings, those are bypassed when
ANTHROPIC_BASE_URLis set. Use MDM to push the environment variable at the OS level — it can't be overridden by a malicioussettings.json.
The Bottom Line
Claude Code is not a web app. It's a terminal-native agent with full filesystem permissions. Treat .claude/settings.json as executable code, route all traffic through a gateway, and lock down filesystem access. The CVEs are patched, but the threat model is permanent.
Source: dev.to








