Repository navigation
fix(skills): make env_passthrough registrations visible across tool context snapshots [risk 0.30] - #131908
Merged
Conversation
૮ >ﻌ< ა ci reviewran on acf6f9d — test(child-env): fixture isolates the process-wide skill pas
|
…ontext snapshots skill_view registers a skill's declared env vars (required_environment_ variables and the legacy prerequisites.env_vars) into the sandbox passthrough allowlist. The allowlist was backed by a ContextVar, and tool dispatch fans each tool call onto a worker whose context is a copy_context() snapshot taken at submit time (tools.thread_context.propagate_context_to_thread). The registration therefore lived and died inside the skill_view worker's snapshot: the submitting thread's context never saw it, and the next tool's snapshot (execute_code, terminal) always started from an empty allowlist — so a skill's env vars were never passed through, on any turn, in any session (#90004). The config-based allowlist (terminal.env_passthrough) is a module-level global and worked, which is why manually adding the var there was the only workaround. Store the skill-registered names in a process-wide set, matching the config path's visibility. Cross-session exposure is limited to the names — values still resolve per profile through resolve_passthrough_value's secret_scope, so a name registered by one session cannot read another profile's secret. clear_env_passthrough keeps its reset semantics; a later skill_view re-registers on demand.
The child_env fixture still reset the allowlist via the removed _allowed_env_vars_var ContextVar token, so every test using the fixture (AttributeError at setup) failed across all Python/OS lanes once #90004's process-wide set landed. Save/restore the set contents instead.
OutThisLife
force-pushed
the
bb/90004-land-90011
branch
from
October 3, 2026 01:27
fc2f997 to
acf6f9d
Compare
OutThisLife
enabled auto-merge (rebase)
October 5, 2026 21:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands #90011 by @liuhao1024 on current main (their commit; conflicts resolved in
tools/env_passthrough.py).The skill env-passthrough allowlist was a session-scoped
ContextVar, but tool dispatch fans each tool call onto a worker whose context is acopy_context()snapshot taken at submit time (tools.thread_context.propagate_context_to_thread). A registration made insideskill_view's worker never reached the submitting thread's context, so the very nextexecute_code/terminalcall re-snapshotted the original (empty) allowlist and the skill's declared env vars (prerequisites.env_vars/required_environment_variables) never passed through — the bundled notion/airtable/gif-search/teams skills failed out of the box (#90004). The allowlist is now a process-wide module-level set (matching the config-based allowlist, which was already a module global). Cross-session exposure is limited to the NAMES: values still resolve per profile throughresolve_passthrough_value's secret scope, and the provider-credential blocklist (GHSA-rhgp-j443-p4rf) still applies at registration.Conflict notes
clear_env_passthrough(called by gateway session reset) keeps working — it clears the same set.Tests
Risk — low-medium: changes process-wide visibility of a security-adjacent allowlist, but only the NAMES cross sessions; values remain profile-scoped and credential-scrubbing is unchanged.
Lint: check-windows-footguns, check_bash_shebangs, check_no_tmp_literals (pre-existing main-only flag), check_config_yaml_writers, check_os_marker_fakes, ruff on changed files — all pass.
Side effects
tests/tools/_child_env_fixtures.pyonly.tools/env_passthrough.pyis core-process code; no client↔server, desktop↔remote-backend or plugin↔host contract changes. Plugins/skills call the sameregister_env_passthroughAPI unchanged._get_allowed/clear_env_passthroughwas grepped — gateway session reset (clear), skill_view registration, execute_code/terminal/build_subprocess_env consumers. The full failing CI surface (test_build_subprocess_env, test_code_execution_modes, test_execute_code_approval_cluster, test_local_env_blocklist, test_env_passthrough, test_skill_env_passthrough) re-ran green locally (all lanes fail on the same fixture AttributeError, fixed by this commit).