fix(security): stop plugin sidecar children inheriting full env - #78033
fix(security): stop plugin sidecar children inheriting full env#78033andrexibiza wants to merge 2 commits into
Conversation
Signed-off-by: Andrex Ibiza, MBA <84248988+andrexibiza@users.noreply.github.com>
Signed-off-by: andrexibiza <84248988+andrexibiza@users.noreply.github.com>
|
suggesting changes The patch sanitizes several direct child launches, but the child-process boundary remains incomplete.
Security evidence:
Targeted Byterover and Google Meet tests pass, and sanitizer checks remove provider, gateway, and password credentials while retaining required plugin values. Review setup: I reviewed a run-owned local rebase or patch replay against current GitHub Not checked:
Signed: GPT-5.6-luna-max in Codex |
Related #77027
What
Five plugin sidecar spawn sites were still copying
os.environraw into child processes, so every child — Playwright's Chromium, themeet_botsubprocess, thebrvCLI, the buzz CLI, and the Photon Node sidecar — inherited the gateway's full credential set (BWS vault token, provider API keys,*_PASSWORDvars) even though the child only needs a handful of plugin-owned values.Each site now builds its child env through the existing sanitized factory
build_subprocess_env()fromtools.environments.local(the same builder every other spawn surface already uses), then applies the site's own additions on top:plugins/google_meet/meet_bot.py:531PULSE_SOURCE,DISPLAY,HERMES_MEET_*(via wholesale env replacement at the merge point so scrubbed credentials can't linger)plugins/google_meet/process_manager.py:135python -m plugins.google_meet.meet_botHERMES_MEET_URL/OUT_DIR/…incl. the explicitly-passedHERMES_MEET_REALTIME_KEYplugins/memory/byterover/__init__.py:137brvCLIPATHprepend of the resolved CLI's bin dirplugins/platforms/buzz/adapter.py:293buzzCLIBUZZ_RELAY_URL,BUZZ_PRIVATE_KEY(the plugin's own child-only secret, applied after sanitizing)plugins/platforms/photon/adapter.py:1598PHOTON_PROJECT_ID/SECRET,PHOTON_SIDECAR_PORT/BIND/TOKEN/WATCH_STDINThe sanitizer is the long-standing scrub owner: the provider env blocklist, the dynamic internal-secret patterns (
GATEWAY_RELAY_*_SECRET/KEY/TOKEN,AUXILIARY_*_API_KEY), andHERMES_HOME/subprocess-HOME propagation.build_subprocess_env()already exists on main and is the documented single factory for child envs — no new machinery.meet_bot detail:
chrome_envis merged back intoos.environbefore Playwright launches (Playwright'slaunch()takes no env dict). The merge is now a wholesale replacement (_apply_chrome_env) of the sanitized env rather than a key-by-key merge, so scrubbed credentials cannot remain in the env Chromium inherits. The realtime API key is resolved and passed explicitly before this point, and the only later env read (HERMES_MEET_LOBBY_TIMEOUT) survives sanitizing, so the bot flow is unchanged.These are the plugin-sidecar sinks flagged in the #77027 credential-boundary review (which hardens the sanitizer itself); this PR applies that sanitizer at the residual plugin spawn sites.
How to test
python -m pytest tests/plugins/test_google_meet_plugin.py tests/plugins/memory/test_byterover_provider.py tests/gateway/test_buzz_adapter.py tests/plugins/platforms/photon/test_sidecar_lifecycle.py -qGATEWAY_RELAY_SECRET,EMAIL_PASSWORD, andOPENAI_API_KEYin the parent env, drive each real spawn seam (mockedPopen/create_subprocess_exec/sidecar spawn; realbuild_subprocess_env()), and assert the child env excludes all three while keeping each plugin's own keys (HERMES_MEET_*,BUZZ_*,PHOTON_*, PATH prepend).hermes meet join, a byterover memory query, a buzz send, orhermes photon setup+gateway connect with aGATEWAY_RELAY_SECRETin the gateway env; the spawned child's/proc/<pid>/environ(orProcess Explorer) no longer contains the gateway's vault token or DB passwords.Platforms
tests/plugins/tests plus the touched test files pass;scripts/check-windows-footguns.pyclean on all changed files;git diff --checkclean.PULSE_SOURCEbranch is Linux-only by design and covered by the seam tests).tests/plugins/…hindsight/image-gen/a2a/kanban/deepinfra tests andtests/tools/test_local_env_blocklist.pyon Windows) reproduce identically on cleanmain.Why this matters to users
Before this change, every time you joined a Google Meet (Chromium child), asked ByteRover to remember something (
brvCLI child), sent a buzz message (CLI child), or ran Photon (Node sidecar), those child processes received a copy of everything in the gateway's environment: the Bitwarden/BWS vault access token, every provider API key, and any*_PASSWORDdatabase/email secrets. A compromised or buggy child (a malicious meet page driving Chromium, a compromised npm dependency in the sidecar, a plugin CLI parsing an odd flag) could read those credentials and exfiltrate the same secrets the gateway itself holds.After this change, each of those children gets only what its job needs: the meeting/CLI/sidecar configuration, the plugin's own relay key or project secret, and the normal non-secret environment. A credential leak in any of those children is now contained to that child's own keys instead of the whole gateway vault.
Part of #78207
Part of #83565 — plugin sidecar children stop inheriting full env; Wave E, direct sibling of the anchor.