fix(cron): no_agent script env comes from the factory's own snapshot, not a raw copy at the spawn site
tests/agent/test_subprocess_env_guard.py flagged cron/scheduler_script.py:362 as a new raw os.environ.copy() spawn-env site. build_subprocess_env gains strip_launch_profile=True so the launch profile's .env residue is still dropped from the base before the secret scrub (same order and semantics as before: strip first, then scope-overlay the owning profile's declared names), and the spawn site no longer snapshots the environ itself.
This commit is contained in:
@@ -343,7 +343,7 @@ def _run_job_script(
|
||||
return False, err
|
||||
|
||||
try:
|
||||
from tools.environments.local import build_subprocess_env, strip_launch_profile_env
|
||||
from tools.environments.local import build_subprocess_env
|
||||
popen_kwargs: dict[str, Any] = {"start_new_session": True}
|
||||
if sys.platform == "win32":
|
||||
popen_kwargs = {
|
||||
@@ -358,8 +358,9 @@ def _run_job_script(
|
||||
# The process env is the LAUNCH profile's. For a job owned by a routed profile, drop that
|
||||
# profile's .env residue from the base first (no-op for the launch profile's own jobs);
|
||||
# the sanitizer then overlays the names the owning profile declares in
|
||||
# terminal.env_passthrough from its own secret scope (#114209).
|
||||
env = build_subprocess_env(strip_launch_profile_env(os.environ.copy()))
|
||||
# terminal.env_passthrough from its own secret scope (#114209). The factory snapshots the
|
||||
# process env itself — no raw copy at the spawn site (test_subprocess_env_guard).
|
||||
env = build_subprocess_env(strip_launch_profile=True)
|
||||
env.update(env_overlay)
|
||||
# Subprocess cwd only (default: scripts-dir parent). NEVER os.chdir() the process.
|
||||
# Use the job's workdir as the subprocess cwd when configured, otherwise default to the scripts-dir
|
||||
|
||||
@@ -332,13 +332,19 @@ def _scrub_credentials(env: dict, *, inherit_credentials: bool) -> dict:
|
||||
|
||||
def build_subprocess_env(
|
||||
base: "Mapping[str, str] | None" = None, *, inherit_profile_home: bool = True,
|
||||
scrub_secrets: bool = True, extra: "Mapping[str, str] | None" = None) -> dict[str, str]:
|
||||
scrub_secrets: bool = True, extra: "Mapping[str, str] | None" = None,
|
||||
strip_launch_profile: bool = False) -> dict[str, str]:
|
||||
"""Single factory for child-process envs. ``base=None`` snapshots ``os.environ``.
|
||||
``scrub_secrets=True`` -> :func:`_sanitize_subprocess_env` (profile home inherent,
|
||||
``inherit_profile_home`` ignored). ``scrub_secrets=False`` keeps the base
|
||||
byte-for-byte (git credential flows, ``bws``/``op``); ``inherit_profile_home``
|
||||
bridges HERMES_HOME + HOME and ``extra`` is applied last so caller overrides win."""
|
||||
bridges HERMES_HOME + HOME and ``extra`` is applied last so caller overrides win.
|
||||
``strip_launch_profile`` drops the LAUNCH profile's ``.env`` residue from the base first
|
||||
(:func:`strip_launch_profile_env`; a no-op unless a routed home is active) so a child that
|
||||
acts for a routed profile sees only that profile's declared names, never the launch profile's."""
|
||||
env: dict[str, str] = dict(base) if base is not None else os.environ.copy()
|
||||
if strip_launch_profile:
|
||||
strip_launch_profile_env(env)
|
||||
if scrub_secrets:
|
||||
return _sanitize_subprocess_env(env, dict(extra) if extra else None)
|
||||
if inherit_profile_home:
|
||||
|
||||
Reference in New Issue
Block a user