fix(cron): only strip launch external-source names when multiplexing
The source-name strip added alongside the external-source fix ran unconditionally. Outside multiplexing there is no other profile to leak from -- os.environ IS this profile's environment -- so popping those names relied on the routed scope overlay putting each one back, which in turn relies on the per-home snapshot recorded at boot. Correct today, but it made a single-profile child's credentials depend on bookkeeping that has nothing to do with isolation. Guard it the way strip_launch_profile_env guards itself: no multiplexing, no strip. A single-profile no_agent child now keeps a byte-identical env even if a source's snapshot were ever missing. Pinned by a regression that runs a real child with a source-owned name in os.environ and no multiplex context; making the strip unconditional fails it. (cherry picked from commit afa429b30a1c9c9b4c011f7d2426a9f099911596)
This commit is contained in:
committed by
kshitij
parent
0943e77136
commit
3dedff6a12
@@ -356,18 +356,22 @@ def _run_job_script(
|
||||
# then overlay the installed scope, then sanitize, so routed values pass the same scrub /
|
||||
# passthrough rules as any other. No-op outside multiplex or for the launch profile's own
|
||||
# fires; the parent process is never mutated.
|
||||
from agent.secret_scope import _is_global_env, current_secret_scope
|
||||
from agent.secret_scope import _is_global_env, current_secret_scope, is_multiplex_active
|
||||
from hermes_cli.env_loader import secret_source_names
|
||||
from tools.environments.local import strip_launch_profile_env
|
||||
base = strip_launch_profile_env(dict(os.environ))
|
||||
# strip_launch_profile_env only knows dotenv- and terminal-config-owned names. External
|
||||
# secret sources (vault, 1Password, ...) also write their names into the shared os.environ,
|
||||
# tracked in secret_source_names(), and a name the LAUNCH profile's source supplied is not
|
||||
# this profile's to see. Drop them all here; the overlay below puts back exactly the ones
|
||||
# the routed profile's own sources supply (build_profile_secret_scope folds them in).
|
||||
for name in secret_source_names():
|
||||
if not _is_global_env(name):
|
||||
base.pop(name, None)
|
||||
# this profile's to see. Drop them; the overlay below puts back exactly the ones the routed
|
||||
# profile's own sources supply (build_profile_secret_scope folds get_secret_source_values in).
|
||||
# Guarded like strip_launch_profile_env itself: with no multiplexing there is no other
|
||||
# profile to leak from -- os.environ IS this profile's environment -- so a single-profile
|
||||
# child keeps byte-identical env even if a source's per-home snapshot is ever missing.
|
||||
if is_multiplex_active():
|
||||
for name in secret_source_names():
|
||||
if not _is_global_env(name):
|
||||
base.pop(name, None)
|
||||
scope = current_secret_scope()
|
||||
if scope:
|
||||
base.update(scope)
|
||||
|
||||
Reference in New Issue
Block a user