[Security] settings.json env vars leak into Bash tool context, bypassing trust boundaries (compounds #69970)

Resolved 💬 1 comment Opened Jun 25, 2026 by pascals-ager Closed Jun 25, 2026

settings.json env vars leak into Bash tool execution context, breaking credential isolation

Summary

When settings.json contains env.AWS_PROFILE (required for Bedrock provider), Claude Code injects this environment variable into the Bash tool execution context. This causes all aws CLI commands to inherit the provider credentials instead of using operational credentials from project-specific configuration.

Combined with bug #69970 (PreToolUse hooks not firing), this creates a complete credential isolation failure with no mechanism for enforcement.

Environment

  • Claude Code: v2.1.191
  • Provider: AWS Bedrock (enabled via CLAUDE_CODE_USE_BEDROCK=1)
  • Use case: Multi-account AWS operations with per-project credential policies

The Design Issue

Context Separation Expected

There should be clear separation between:

  1. Provider context - credentials for Claude Code to access Bedrock API for LLM inference
  2. Operational context - credentials for user commands (aws, terraform, etc.) to operate on infrastructure

Actual Behavior

// ~/.claude/settings.json
{
  "env": {
    "AWS_PROFILE": "bedrock-api-profile",
    "AWS_REGION": "us-east-1"
  }
}

This profile is needed for Claude Code to call Bedrock. However:

  1. Claude Code injects these env vars into the Bash tool execution environment
  2. All aws commands inherit AWS_PROFILE=bedrock-api-profile automatically
  3. Commands execute in the provider account, not the intended operational account
# User expects this to use project-specific credentials:
$ aws sts get-caller-identity

# Actually executes as:
$ AWS_PROFILE=bedrock-api-profile aws sts get-caller-identity
# Returns: Account 111111111111 (Bedrock/provider account)
# Expected: Account 222222222222 (operational/project account)

Compounding with Bug #69970

The intended safeguard is PreToolUse hooks that:

  1. Detect AWS commands without explicit operational credentials
  2. Inject/enforce project-specific credentials
  3. Block commands that would use ambient provider credentials

However, bug #69970 (PreToolUse hooks not firing) means:

  • Hooks never intercept to validate/override the inherited profile
  • All AWS commands silently use provider credentials
  • No warning, no blocking, no enforcement

Impact

Infrastructure Operations in Wrong Account

# Intended: provision RDS in operational account (222222222222)
$ terraform apply

# Actual: provisions RDS in provider account (111111111111)
# - Wrong VPC, wrong security boundaries
# - Resources billed to provider account
# - Violates organizational AWS account structure

Silent Policy Violations

With hooks working, this would be caught:

🚨 Blocked: AWS command using ambient credentials (AWS_PROFILE=bedrock-api-profile)
   Expected: Explicit profile from project configuration

With hooks broken (bug #69970), no detection occurs.

Root Cause

settings.json serves two incompatible purposes:

  1. Claude Code runtime configuration - how the harness itself operates (provider access)
  2. User environment template - env vars injected into tool execution contexts

When these overlap (both need AWS_PROFILE), provider credentials pollute operational context.

Reproduction

Setup

  1. Configure Bedrock provider:
{
  "env": {
    "CLAUDE_CODE_USE_BEDROCK": "1",
    "AWS_PROFILE": "my-bedrock-profile",
    "AWS_REGION": "us-east-1"
  }
}
  1. Create project with different operational credentials:
# Project expects operations in account 222222222222
# Provider (Bedrock) operates in account 111111111111
  1. Verify hooks are not firing (bug #69970):
$ grep -c '"hookResult"' ~/.claude/history.jsonl
0  # Hooks not firing

Observe

$ claude
> run: aws sts get-caller-identity

Expected: Command blocked or uses project-specific credentials
Actual: Returns account 111111111111 (provider account)

Inspect environment:

> run: env | grep AWS_PROFILE
AWS_PROFILE=my-bedrock-profile

This was injected by Claude Code from settings.json.

Proposed Solutions

Option 1: Namespace Separation (Preferred)

Provider credentials should use a separate namespace that doesn't leak into tool execution:

{
  "provider": {
    "bedrock": {
      "profile": "my-bedrock-profile",
      "region": "us-east-1"
    }
  },
  "env": {
    // Only env vars intended for user commands
  }
}

Claude Code internally uses provider.bedrock.* for API calls.
Bash tool environment only gets env.* values.

Option 2: Explicit Provider Env Isolation

Keep current structure but isolate provider env vars:

{
  "providerEnv": {
    "AWS_PROFILE": "my-bedrock-profile"
  },
  "toolEnv": {
    // Injected into Bash/tool contexts
  }
}

Option 3: Hook-Mandatory Mode

When PreToolUse hooks are registered, make them a hard requirement:

  • Session fails to start if hooks are broken (bug #69970)
  • Forces fail-safe: better to not run than to run with bypassed safeguards

Workaround (Current)

Until fixed, users must:

  1. Never set AWS_PROFILE in settings.json env - breaks Bedrock provider
  2. Always use explicit credentials - requires perfect discipline:

``bash
AWS_CONFIG_FILE="$PWD/config" AWS_PROFILE="ops-profile" aws ...
``

  1. Add manual validation to every AWS operation

All workarounds are fragile when hooks don't fire (bug #69970).

References

  • Bug #69970: PreToolUse:Bash hooks not invoked (the enforcement mechanism that should catch this)
  • This issue: Design flaw that creates the vulnerability #69970 fails to prevent

Security Implications

When provider credentials and operational credentials mix:

  • Multi-account AWS strategies break
  • Billing/compliance boundaries violated
  • Infrastructure provisioned in wrong security contexts
  • No audit trail (commands succeed, wrong account)

This is particularly severe for:

  • Organizations with separate provider/operational accounts
  • Multi-tenant or multi-project setups
  • Compliance environments requiring strict account boundaries
  • Plugin-based credential enforcement systems

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗