Skip to content

fix(task): preserve essential env vars under deny_env on Linux#9467

Merged
jdx merged 1 commit intomainfrom
claude/suspicious-stonebraker-20691e
Apr 29, 2026
Merged

fix(task): preserve essential env vars under deny_env on Linux#9467
jdx merged 1 commit intomainfrom
claude/suspicious-stonebraker-20691e

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 29, 2026

Summary

  • Fixes #9466: under deny_env = true on Linux, every env var was stripped from the child process — including the PATH/HOME/USER/SHELL/TERM/LANG that the docs and filter_env say should pass through.
  • Root cause: apply_sandbox() called Command::env_clear() after task_executor had already populated the command via .envs(filtered_env). env_clear() wipes both inherited and explicitly-set envs, leaving an empty environment. The macOS branch already handled this (it builds a new command and copies the envs over); the Linux branch did not.
  • Fix: on Linux, snapshot the explicit envs, call env_clear() (still needed to prevent parent inheritance), then re-apply the saved envs.
  • Extended e2e/sandbox/test_sandbox_task with a path_test task that asserts PATH and HOME are non-empty under deny_env, so this regression gets caught next time.

Test plan

  • cargo build
  • cargo test --bin mise sandbox::tests
  • mise run test:e2e sandbox/test_sandbox_task (passes on macOS; new assertions exercise the Linux-only code path in CI)
  • mise run lint-fix

🤖 Generated with Claude Code


Note

Medium Risk
Touches process execution/sandbox setup on Linux; mistakes could leak env vars or break task execution, but the change is small and covered by a new regression test.

Overview
Fixes Linux deny_env sandbox behavior so clearing inherited environment variables no longer removes env vars explicitly set on the Command (e.g., filtered essentials like PATH/HOME). It snapshots Command::get_envs(), calls env_clear(), then restores the saved key/values before applying Landlock/seccomp.

Adds an e2e regression check (sandbox/test_sandbox_task) that verifies deny_env still preserves PATH and HOME while continuing to hide a secret env var.

Reviewed by Cursor Bugbot for commit 9b6eca7. Bugbot is set up for automated code reviews on this repo. Configure here.

env_clear() in apply_sandbox() ran after the task executor had already
populated Command with the filtered env (PATH, HOME, USER, SHELL, TERM,
LANG plus any allow_env entries), wiping them all. Save the explicit
envs, clear, then restore — matching the existing macOS path.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 29, 2026

Greptile Summary

This PR fixes a Linux-specific regression where deny_env = true stripped all environment variables — including essential ones like PATH and HOME — from child processes. The root cause was that apply_sandbox() called env_clear() after task_executor had already populated the command via .envs(filtered_env), wiping both inherited and explicitly-set vars. The fix snapshots the explicitly-set envs before env_clear() and restores them afterward, mirroring the behavior that the macOS branch already achieved by construction.

Confidence Score: 5/5

Safe to merge — the fix is minimal, targeted, and matches the established macOS pattern.

No P0/P1 issues found. The save-then-restore pattern correctly mirrors how the macOS branch already handled this. get_envs() returning None for explicitly-removed vars is correctly handled by the filter_map. A regression test exercises the new code path in CI on Linux.

No files require special attention.

Important Files Changed

Filename Overview
src/cmd.rs Linux apply_sandbox() now saves and restores explicitly-set envs around env_clear(), preserving essential vars that filter_env() had already computed.
e2e/sandbox/test_sandbox_task Adds a path_test task and two assert_not_contains assertions verifying that PATH and HOME are non-empty under deny_env = true.

Sequence Diagram

sequenceDiagram
    participant TE as task_executor
    participant CMD as Command
    participant AS as apply_sandbox()
    participant PROC as Child Process

    TE->>CMD: .envs(filter_env(env))
    TE->>AS: apply_sandbox()
    note over AS: effective_deny_env() == true
    AS->>CMD: get_envs() → save explicitly-set vars
    AS->>CMD: env_clear() (wipes inherited + explicit)
    AS->>CMD: re-apply saved vars (PATH, HOME, ...)
    AS->>CMD: pre_exec(landlock/seccomp)
    CMD->>PROC: spawn() — child sees only filtered vars
Loading

Reviews (1): Last reviewed commit: "fix(task): preserve essential env vars u..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Linux command runner to ensure that environment variables explicitly set via .envs() are preserved when deny_env is enabled, as env_clear() previously wiped them. It also adds an end-to-end test to verify that essential environment variables like PATH and HOME remain accessible under these conditions. I have no feedback to provide.

@jdx jdx enabled auto-merge (squash) April 29, 2026 13:25
@jdx jdx merged commit a82834d into main Apr 29, 2026
38 checks passed
@jdx jdx deleted the claude/suspicious-stonebraker-20691e branch April 29, 2026 13:36
@github-actions
Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 x -- echo 23.4 ± 0.7 22.0 34.0 1.00
mise x -- echo 24.6 ± 0.9 22.6 30.0 1.05 ± 0.05

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 env 22.9 ± 0.8 21.3 29.7 1.00
mise env 23.7 ± 0.6 22.3 25.8 1.04 ± 0.04

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 hook-env 23.2 ± 0.7 22.1 28.5 1.00
mise hook-env 24.4 ± 0.6 23.0 27.2 1.05 ± 0.04

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.25 ls 24.1 ± 0.5 23.0 26.5 1.00
mise ls 24.9 ± 0.5 23.6 27.5 1.03 ± 0.03

xtasks/test/perf

Command mise-2026.4.25 mise Variance
install (cached) 158ms 164ms -3%
ls (cached) 81ms 84ms -3%
bin-paths (cached) 82ms 85ms -3%
task-ls (cached) 861ms 818ms +5%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant