Claude Code's Keychain Storage: What It Actually Secures (And What It Doesn't)

Claude Code's Keychain Storage: What It Actually Secures (And What It Doesn't)

Claude Code 2.1.83's new keychain storage prevents credential leaks, but proper plugin architecture is what keeps your API keys safe from the model.

GAlex Martin & AI Research Desk·4h ago·4 min read·2 views·AI-Generated
Share:
Source: dev.tovia devto_anthropicSingle Source
Claude Code's Keychain Storage: What It Actually Secures (And What It Doesn't)

Claude Code 2.1.83 shipped a critical security feature: plugin credential management. If you're building or using plugins that connect to external APIs, you need to understand what this does—and what it doesn't do—to use it effectively.

What Changed in 2.1.83

When you install a plugin that declares credential requirements, Claude Code now prompts for those values upfront and stores them in your OS keychain (macOS Keychain or Windows Credential Manager). This replaces the old pattern of storing credentials in plaintext files like ~/.claude/settings.json or project .env files.

The companion feature: CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1. When enabled, this strips credentials from subprocess environments—preventing leaks to bash tools, hooks, and MCP stdio servers.

The immediate win: credentials won't accidentally end up in git commits, get scraped by background processes, or remain on shared machines.

What Keychain Storage Doesn't Do

This is crucial: keychain storage is not a permission sandbox. It securely stores your credential, but doesn't restrict what that credential can do. If you store a full-access Stripe API key in the keychain, you have a full-access key stored securely—not a restricted key.

Cover image for Claude Code plugin credentials: what the new keychain storage does and doesn't do

The real security comes from plugin architecture, not just the storage mechanism.

The Right Way to Build Secure Plugins

A properly architected plugin never exposes the API key to Claude at all. Here's the flow:

  1. Claude invokes your plugin's tool (like get_charges)
  2. Plugin reads the key from keychain
  3. Plugin makes the API call
  4. Plugin returns structured data
  5. Claude sees only the data, never the credential

Here's the Python pattern:

import stripe
import keyring

def get_plugin_client():
    api_key = keyring.get_password("claude-plugin-stripe", "api_key")
    return stripe.StripeClient(api_key)

def get_charges(customer_id: str, limit: int = 10):
    client = get_plugin_client()
    charges = client.charges.list(customer=customer_id, limit=limit)
    return [
        {
            "id": c.id,
            "amount": c.amount,
            "currency": c.currency,
            "created": c.created,
            "status": c.status,
            "description": c.description
        }
        for c in charges.data
    ]

The key stays in keychain. Claude never sees it. This creates a stronger trust boundary than most developers assume.

Enable Subprocess Scrubbing Now

Without CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1, credentials in Claude Code's environment can leak to child processes. If STRIPE_API_KEY is in your environment and Claude spawns a bash tool, that variable is accessible.

Add this to your shell configuration:

export CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1

This closes a specific attack vector where compromised hooks or MCP servers could read credentials from the environment.

The Real Risk: Prompt Injection in Returned Data

Here's the attack surface people underestimate. Your plugin reads customer data from Stripe and returns it to Claude. What's in that data? Whatever the customer put there—including potentially malicious prompt injections in metadata fields.

If your plugin returns raw API objects directly, you're feeding potential prompt injections into Claude's context. Always sanitize or structure the data before returning it (like the example above that returns specific fields, not raw objects).

Defense in Depth: Three Independent Layers

Build security with three layers, so if one fails, the others still protect you:

  1. Plugin code hardcoded to read endpoints - No write functions exist in the plugin
  2. Restricted API keys at the provider level - Create keys scoped to specific resources and permissions
  3. Keychain storage - Prevents plaintext credential exposure

If the plugin code is bypassed, the restricted key prevents writes. If the key is misconfigured, the plugin code won't attempt writes. If both fail, at least the key wasn't trivially accessible.

Practical Takeaways for Plugin Developers

  1. Declare credential requirements in your plugin manifest so they get stored in keychain on install
  2. Enable CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 in your environment
  3. Create restricted API keys at the provider level with minimum permissions
  4. Return structured data, not raw API objects to prevent prompt injection
  5. Keep plugin scope narrow - less surface area for manipulation

The keychain feature is one piece of the security story, not the whole solution. Proper architecture matters more than the storage mechanism.

AI Analysis

Claude Code users should immediately enable `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1` in their environment—this is a simple one-line addition to your shell config that closes a credential leak vector. For developers building plugins, the key insight is that security comes from architecture, not just storage: design your plugins to never expose credentials to Claude's context, always use restricted API keys, and sanitize returned data. This follows Claude Code's continued integration with the Model Context Protocol (MCP) ecosystem we've covered extensively. The credential management system aligns with Anthropic's broader security-first approach seen in Claude Opus 4.6's handling of sensitive data. As more developers build production plugins, understanding this defense-in-depth approach becomes critical—especially as Claude Agent frameworks increasingly rely on Claude Code for execution. When evaluating third-party plugins, check if they follow these patterns: do they request minimal permissions? Do they return structured data rather than raw API responses? The keychain feature makes plugin installation safer, but you still need to vet the plugin architecture itself.
Enjoyed this article?
Share:

Related Articles

More in Products & Launches

View all