Skip to content

fix(security): include AWS credential vars in bedrock subprocess blocklist (#32314) - #32319

Closed
briandevans wants to merge 2 commits into
NousResearch:mainfrom
briandevans:fix/bedrock-aws-credential-blocklist-32314
Closed

fix(security): include AWS credential vars in bedrock subprocess blocklist (#32314)#32319
briandevans wants to merge 2 commits into
NousResearch:mainfrom
briandevans:fix/bedrock-aws-credential-blocklist-32314

Conversation

@briandevans

Copy link
Copy Markdown
Contributor

What does this PR do?

The built-in bedrock provider uses auth_type=\"aws_sdk\" and previously declared api_key_env_vars=() — an empty tuple. The subprocess sanitization in tools/environments/local.py::_build_provider_env_blocklist() iterates each provider's api_key_env_vars to derive its blocklist, so AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BEARER_TOKEN_BEDROCK, AWS_PROFILE, …) were never blocked and inherited into agent-spawned terminal/execute_code/MCP subprocesses. Any subprocess that auto-discovers AWS credentials (e.g. opencode models) silently saw the user's full Bedrock catalog and could make Bedrock or other AWS API calls the agent did not intend to expose.

This populates bedrock.api_key_env_vars with the canonical AWS SDK credential set so the existing blocklist mechanism strips them. The set mirrors agent/bedrock_adapter.py::_AWS_CREDENTIAL_ENV_VARS (the runtime detector used by resolve_aws_auth_env_var()) plus the paired secret/session vars boto3 reads via its default credential chain.

Mirrors agent/bedrock_adapter.py::_AWS_CREDENTIAL_ENV_VARS precedence: AWS_BEARER_TOKEN_BEDROCK > AWS_ACCESS_KEY_ID(+AWS_SECRET_ACCESS_KEY,+AWS_SESSION_TOKEN) > AWS_PROFILE > AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > AWS_WEB_IDENTITY_TOKEN_FILE.

The _HERMES_PROVIDER_ENV_FORCE_ opt-in path still works for legitimate AWS-aware subprocesses that need to inherit credentials (the standard escape hatch for the rest of the blocklist).

Related Issue

Fixes #32314

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • `hermes_cli/auth.py` — populate `bedrock.api_key_env_vars` with the canonical AWS SDK credential set (10 vars: bearer token, access-key pair + session token, profile, role-ARN, web-identity, container-credential URIs and authorization token).
  • `tests/tools/test_local_env_blocklist.py` — add two regression tests: one asserts AWS vars are stripped from a LocalEnvironment subprocess env via the existing harness; the other asserts the same vars are present in `_HERMES_PROVIDER_ENV_BLOCKLIST`. Both fail on `main` without the auth.py change.

How to Test

  1. `uv run --with pytest --with pytest-xdist --with pytest-asyncio python3 -m pytest tests/tools/test_local_env_blocklist.py -v` → 20 passed (was 18, added 2).
  2. End-to-end repro: configure `provider: bedrock`, export `AWS_BEARER_TOKEN_BEDROCK=...`, run a terminal session via Hermes, `env | grep AWS` → before: full set leaked; after: empty.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (`fix(security):`)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix (no unrelated commits)
  • I've run focused tests for the touched code and all pass
  • I've added tests for my changes
  • I've tested on my platform: macOS 15.x

Documentation & Housekeeping

  • I've updated relevant documentation — N/A (the blocklist is internal mechanism; behavior is documented by the regression tests)
  • I've updated `cli-config.yaml.example` if I added/changed config keys — N/A
  • I've updated `CONTRIBUTING.md` or `AGENTS.md` if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — pure registry data change, OS-agnostic
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Related / Positioning

Audited siblings

Only one provider in PROVIDER_REGISTRY declares auth_type=\"aws_sdk\" today (bedrock at `hermes_cli/auth.py:450`); the other two non-api_key/non-oauth providers are `external_process` and `oauth_minimax`, which use their own credential surfaces. No widening needed.

Copilot AI review requested due to automatic review settings May 26, 2026 00:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds AWS SDK credential environment variables to Hermes’ subprocess environment blocklist (via Bedrock provider config) to prevent credential leakage, with regression tests for issue #32314.

Changes:

  • Populate Bedrock (auth_type="aws_sdk") api_key_env_vars with standard AWS credential/config env vars so they’re stripped from subprocess env.
  • Add regression test ensuring AWS credential env vars are removed from subprocess environment.
  • Add regression test ensuring AWS SDK provider vars are included in the global provider env blocklist.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
tests/tools/test_local_env_blocklist.py Adds regression tests asserting AWS credential vars are stripped and included in the blocklist.
hermes_cli/auth.py Updates Bedrock provider config to include AWS credential-related env vars in api_key_env_vars for blocklisting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +123 to +136
aws_vars = {
"AWS_BEARER_TOKEN_BEDROCK": "bedrock-bearer-secret",
"AWS_ACCESS_KEY_ID": "AKIA-fake",
"AWS_SECRET_ACCESS_KEY": "fake-secret",
"AWS_SESSION_TOKEN": "fake-session",
"AWS_PROFILE": "prod",
"AWS_ROLE_ARN": "arn:aws:iam::123:role/x",
"AWS_WEB_IDENTITY_TOKEN_FILE": "/tmp/token",
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI": "/v2/credentials/abc",
}
result_env = _run_with_env(extra_os_env=aws_vars)

for var in aws_vars:
assert var not in result_env, f"{var} leaked into subprocess env"
"AWS_PROFILE",
"AWS_ROLE_ARN",
"AWS_WEB_IDENTITY_TOKEN_FILE",
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
Comment thread hermes_cli/auth.py Outdated
Comment on lines +455 to +470
# Listed here so tools/environments/local.py's subprocess blocklist
# strips them — otherwise AWS creds leak into terminal/execute_code.
# Mirrors agent/bedrock_adapter.py::_AWS_CREDENTIAL_ENV_VARS plus the
# paired secret/session vars boto3 also reads via its default chain.
api_key_env_vars=(
"AWS_BEARER_TOKEN_BEDROCK",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
"AWS_PROFILE",
"AWS_ROLE_ARN",
"AWS_WEB_IDENTITY_TOKEN_FILE",
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
"AWS_CONTAINER_AUTHORIZATION_TOKEN",
),
@alt-glitch alt-glitch added type/security Security vulnerability or hardening P1 High — major feature broken, no workaround comp/cli CLI entry point, hermes_cli/, setup wizard provider/bedrock AWS Bedrock (boto3, IAM) area/auth Authentication, OAuth, credential pools tool/terminal Terminal execution and process management tool/code-exec execute_code sandbox labels May 26, 2026
@briandevans

Copy link
Copy Markdown
Contributor Author

CI fixup in 338660514: moved the AWS credential env vars out of the bedrock ProviderConfig.api_key_env_vars tuple (which broke tests/agent/test_bedrock_integration.py::test_bedrock_has_no_api_key_env_vars — bedrock's auth_type="aws_sdk" invariant requires that tuple to stay empty) and into the hardcoded extras set inside _build_provider_env_blocklist() in tools/environments/local.py. Same blocklist coverage; the #32314 regression tests in tests/tools/test_local_env_blocklist.py still pass, and the bedrock invariant is restored. 75 passed locally.

@mobilinkd

Copy link
Copy Markdown

This new change is wrong. The original fix was correct and the invariant is completely bogus. It must be replaced with the exact opposite assertion -- that all of the listed environment variables are present.

…klist (NousResearch#32314)

The built-in `bedrock` provider uses `auth_type="aws_sdk"` and previously
declared `api_key_env_vars=()` — empty. The subprocess sanitization in
`tools/environments/local.py::_build_provider_env_blocklist()` iterates
`pconfig.api_key_env_vars` to derive its blocklist, so AWS credentials
(`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_BEARER_TOKEN_BEDROCK`,
`AWS_PROFILE`, etc.) were never blocked and inherited into agent-spawned
terminal/execute_code/MCP subprocesses. Any subprocess that auto-discovers
AWS credentials (e.g. `opencode models`) silently saw the user's full
Bedrock catalog and could make Bedrock or other AWS calls the agent did
not intend to expose.

Populate `bedrock.api_key_env_vars` with the canonical AWS SDK credential
set so the existing blocklist mechanism strips them. The set mirrors
`agent/bedrock_adapter.py::_AWS_CREDENTIAL_ENV_VARS` (the runtime detector
used by `resolve_aws_auth_env_var()`) plus the paired secret/session vars
that boto3 reads via its default credential chain.

The `_HERMES_PROVIDER_ENV_FORCE_` opt-in path still works for legitimate
AWS-aware subprocesses that need the credentials.

Tests:
- `tests/tools/test_local_env_blocklist.py::TestProviderEnvBlocklist::test_aws_credential_vars_are_stripped`
  asserts the full set is removed from a LocalEnvironment subprocess env.
- `tests/tools/test_local_env_blocklist.py::TestBlocklistCoverage::test_aws_sdk_provider_vars_covered`
  asserts the set is present in `_HERMES_PROVIDER_ENV_BLOCKLIST`.
Both fail on main without the auth.py change.
Listing the AWS credential env vars on bedrock's ProviderConfig as
api_key_env_vars broke the test_bedrock_has_no_api_key_env_vars
invariant — bedrock uses auth_type="aws_sdk" by design, so its
api_key_env_vars must stay empty.

Move the AWS_BEARER_TOKEN_BEDROCK / AWS_ACCESS_KEY_ID / AWS_PROFILE /
session/role/container vars into the hardcoded extras set inside
_build_provider_env_blocklist() instead. Same blocklist coverage, no
schema overload — the regression test for NousResearch#32314 still passes because
the vars are still present in _HERMES_PROVIDER_ENV_BLOCKLIST, just
sourced from the extras list rather than the registry derivation.
@teknium1

Copy link
Copy Markdown
Contributor

Superseded by #34498 (merged to main). Thanks for the early + well-tested catch on #32314 — you correctly identified that bedrock's api_key_env_vars=() left AWS creds out of the subprocess blocklist.

The merged fix narrows the strip to AWS_BEARER_TOKEN_BEDROCK only (the Hermes inference secret) and deliberately leaves the general AWS credential chain inheritable. Hard-blocklisting the full chain would regress every user who runs aws/terraform/boto3 in the agent terminal (the registry is iterated unconditionally, so it's not scoped to Bedrock users) and would be unrecoverable via env_passthrough per GHSA-rhgp-j443-p4rf. Per SECURITY.md §3.2 the local terminal is the user's trusted operator shell. Appreciate the contribution.

@teknium1 teknium1 closed this May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard P1 High — major feature broken, no workaround provider/bedrock AWS Bedrock (boto3, IAM) tool/code-exec execute_code sandbox tool/terminal Terminal execution and process management type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: auth_type="aws_sdk" never feeds into subprocess credential blocklist; AWS env vars leak to terminal/execute_code

5 participants