fix(secrets): scope BWS-injected provider keys - #58111
Conversation
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved (read-only token - formal approval deferred)
Security fix: scope BWS-injected provider keys so they don't leak across profile boundaries. Adds tracking to associate Bitwarden-sourced secrets with their profile home, and filters by home in . Also fixes to handle explicitly. No concerns.
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved (read-only token - formal approval deferred)
Security fix: scope BWS-injected provider keys so they don't leak across profile boundaries. Adds _SECRET_SOURCE_HOMES tracking to associate Bitwarden-sourced secrets with their profile home, and filters by home in build_profile_secret_scope. Also fixes get_env_value_prefer_dotenv to handle UnscopedSecretError explicitly. No concerns.
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved (LGTM)
Scopes BWS-injected provider keys to the correct namespace. Security-relevant fix.
What Looks Good
- Security-relevant fix
- Well-scoped
- No debug artifacts
Reviewed by Hermes Agent
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: LGTM
Fix (+189/-2) scoping BWS-injected provider keys to the secrets system. Security-focused fix with proper secret scope handling.
Looks Good
- Proper secret scoping design
- No security or performance concerns
Reviewed by Hermes Agent
|
Thanks for pursuing the safer scoped-secret direction; the current-main cron/profile failure is real. Problems
Suggested changes
Automated hermes-sweeper review. |
dea78a4 to
5fa4edb
Compare
Snapshot values applied by external secret sources per resolved HERMES_HOME so a later profile cannot replace an earlier profile scope through shared os.environ. Keep provider and credential-pool fallback reads on the active secret scope, and fail closed on unscoped multiplex reads. Tests: scripts/run_tests.sh tests/test_env_loader_secret_sources.py tests/test_env_loader_op_bootstrap.py tests/agent/test_secret_scope.py tests/agent/test_credential_pool.py tests/tools/test_credential_pool_env_fallback.py tests/hermes_cli/test_xiaomi_provider.py tests/cron/test_run_one_job.py tests/hermes_cli/test_api_key_providers.py tests/gateway/test_multiplex_credential_isolation.py -q (395 passed)
5fa4edb to
a292f78
Compare
|
Addressed in a292f78. I ported the fix to current main's generic report.provenance API and now snapshot the sanitized secret values per resolved HERMES_HOME at apply time, so a later home cannot change an earlier profile's scope through shared os.environ. |
|
Merged via #69250 — your commit landed as-is (rebase-merged, authorship preserved). The per-home value snapshot was exactly the right design: values recorded at the only moment they're unambiguous, so a later profile's apply can never mutate an earlier profile's scope through shared os.environ. Only fixups from us: a test-file cherry-pick conflict and one fake ApplyReport needing a SourceReport after the #69056 guard landed. Fixes #58100. Thanks @izumi0uu — third landed contribution in this secrets sweep! |
What does this PR do?
Fixes provider credential resolution when Bitwarden/BSM injects API keys into
os.environduringload_hermes_dotenv(), but cron/profile execution later runs under an authoritative profile secret scope.The fix records which
HERMES_HOMEan external secret source was applied for, then includes only those same-home external secrets when building that profile'ssecret_scope. This lets BWS-backed provider keys resolve in cron/profile-scoped paths without adding an unsafe rawos.environfallback for scoped-missing keys.It also preserves fail-closed behavior for unscoped multiplex credential reads:
UnscopedSecretErroris no longer swallowed into a raw-env fallback byget_env_value_prefer_dotenv().Related Issue
Fixes #58100
Type of Change
Changes Made
hermes_cli/env_loader.py.build_profile_secret_scope().How to Test
.venv/bin/python -m pytest tests/test_env_loader_secret_sources.py tests/agent/test_secret_scope.py tests/hermes_cli/test_xiaomi_provider.py tests/cron/test_run_one_job.py -q.venv/bin/python -m pytest tests/hermes_cli/test_api_key_providers.py tests/gateway/test_multiplex_credential_isolation.py -q.venv/bin/python -m ruff check hermes_cli/env_loader.py agent/secret_scope.py hermes_cli/config.py tests/test_env_loader_secret_sources.py tests/agent/test_secret_scope.py tests/hermes_cli/test_xiaomi_provider.pyChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — N/Acli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/AScreenshots / Logs
Before the fix, an active profile scope with no
XIAOMI_API_KEYreturned an empty provider credential even when BWS had injectedXIAOMI_API_KEYintoos.environ.After the fix, a same-home external secret resolves:
A scoped-missing raw env var still does not leak across profiles: