Repository navigation
fix(utils): keep project-dotenv interpreter and loader injection variables out of the bash tool - #6746
Conversation
probepark
left a comment
There was a problem hiding this comment.
Code review (CI still running on 7b9e06b; approval decision follows once CI finishes).
Review (head 7b9e06b, gajae-reviewer on behalf of probepark)
Blocking: None found in the code review.
ocr: blocking 0 / nit 0
CI: Approval held. gajae-approve-gate.py 6746 --head 7b9e06b2c025b383c9de72e089c9950485056dcd returned HOLD_CI (exit 10). Pending: install-methods and the Affected path validation aggregate. The gate also reports a CI-plan gap: cd packages/coding-agent && bun run check. Recheck the gate after CI finishes; if that gap remains, run the command at this exact head and re-request review.
Scope: +151 / -4, 6 files: utils spawn environment, real bash-path regressions, documentation, and a changelog fragment. OCR selected one production file (+8 / -3).
Conventions: Changelog fragment present. No released changelog edits, generated-file changes, or labels.
Notable:
packages/utils/src/shell-config.ts:68-89— All seven new variables use the existing anchored denylist and provenance filter. Distinct inherited values remain allowed; matching or dynamic project declarations fail closed.packages/coding-agent/src/exec/bash-executor.ts:445-451andpackages/coding-agent/src/tools/bash-interactive.ts:327-328— Native execution and PTY unset handling consume the same filter. Isolated worker, guardian, and supervisor spawn paths callprojectSafeSpawnEnv.packages/coding-agent/test/bash-project-hook-env.test.ts:169-275— New tests use real interpreters and payload markers, not module mocks. Exact-head CI executed Node, Python, Perl, Java, and LD_PRELOAD cases, plus the trusted-PYTHONPATH positive case.
Evidence: The bash-path CI command bun scripts/ci-dev-affected.ts --task="$AFFECTED_TASK_KEY" ran at this head. It reported 23 pass / 0 fail at 2026-10-14 06:59:30 UTC. Job: https://github.com/Yeachan-Heo/gajae-code/actions/runs/38523783394/job/115724284765 . Utils checks and spawn-env tests also have successful check results. No local builds or tests were run in this review environment.
Claim assessment: The PR's stated denylist extension matches the code. Shared environment behavior and the Python-kernel allowlist remain unchanged.
Checked and clean: Changed production code, provenance integration, spawn-path call sites, documentation, changelog placement, and exact-head Linux payload regressions.
Not assessed: A real macOS DYLD_INSERT_LIBRARIES payload, deliberately excluded Ruby/interactive Python vectors, and full coding-agent lint/typecheck evidence. The latter remains a gate-reported plan gap, not a code finding.
Verdict: Code-reviewed with blocking=0; no APPROVE while CI remains pending. PR body unchanged.
probepark
left a comment
There was a problem hiding this comment.
Approve held: CI plan did not run cd packages/coding-agent && bun run check on 7b9e06b.
Run that command at this exact head, record the command, head SHA, and exit code, then re-request review.
Blocking: No code findings. The earlier exact-head code review remains applicable: #6746 (review) .
ocr: blocking 0 / nit 0
CI: CI finished with no pending or failed checks reported by the approval gate. The required coding-agent biome/typecheck command is absent from the head CI plan. Utils checks are covered.
Verification: python3 /opt/data/scripts/gajae-approve-gate.py 6746 --head 7b9e06b2c025b383c9de72e089c9950485056dcd returned NEED_LOCAL (exit 11) during this gate-only follow-up on 2026-10-14. The PR remains OPEN at that head, rechecked at 07:21:36 UTC. No local builds or tests were run in this review environment. The PR description reports local checks, but does not provide an exact-head command/exit record sufficient to resolve this gate.
Verdict: Approval held for missing verification, not a code defect. PR body unchanged.
snowykr
left a comment
There was a problem hiding this comment.
Verdict
CHANGES_REQUESTED
Summary
The PR extends provenance-aware filtering of project dotenv values for bash-tool subprocesses and adds end-to-end tests and documentation. A remaining dynamic-loader path allows project-controlled environment values to load repository code in eligible child processes, so the protection is incomplete.
Findings / Required Changes
- [P2] Filter remaining project-controlled loader controls —
packages/utils/src/shell-config.ts:68-69- The base also allowed these variables, but this change adds only
LD_PRELOADandDYLD_INSERT_LIBRARIES; the new denylist still omitsLD_AUDIT,LD_LIBRARY_PATH, and DYLD search-path overrides such asDYLD_LIBRARY_PATHandDYLD_FALLBACK_LIBRARY_PATH. Only names matched by the denylist are returned for stripping (packages/utils/src/shell-config.ts:81-89), and the resulting environment reaches bash-tool workers and child processes (packages/utils/src/shell-config.ts:124-126;packages/coding-agent/src/exec/isolated-shell.ts:87-93). - With a project
.envsettingLD_AUDIT, a normal Linux dynamically linked child can load a project-provided audit module; loader search-path values can instead redirect a command's library resolution to a project-controlled shared object. This requires a compatible process/library load and runs with the user's existing authority, not elevated privileges, but defeats the intended project-dotenv injection boundary. Repository code also treatsLD_LIBRARY_PATH/DYLD overrides as unsafe (packages/coding-agent/src/gjc-runtime/ultragoal-evidence.ts:373-374;packages/natives/native/diagnostic-loader.js:48-50). - Extend the provenance-aware denylist to cover
LD_AUDITand the applicable loader search-path overrides, and test the spawn boundary while preserving the existing handling of distinct operator-inherited values. This is a concrete gap in the loader-protection follow-up, not a separate regression from base.
- The base also allowed these variables, but this change adds only
CI / Verification
Dev CI run 38523783394 completed successfully on the reviewed head. The affected-path test jobs for packages/coding-agent/test/bash-project-hook-env.test.ts and packages/utils/test/shell-spawn-env-trust.test.ts, the utils check, install-methods, the affected-path aggregate, and virtual integration validation reported success. The virtual-integration evidence/canary steps were planner-skipped, so they are not treated as executed. Existing tests cover the listed interpreter variables and LD_PRELOAD; they do not exercise the omitted loader controls, which is relevant to finding 1. No local tests or exploit probes were run as part of this review.
Axis Coverage
| Axis | Verdict | Coverage |
|---|---|---|
| A1 — Intent / Policy / Contract | APPROVED |
No separate intent mismatch; the PR body enumerates specific additions. The single loader-boundary finding is captured below. |
| A2 — Architecture / Correctness / Failure | CHANGES_REQUESTED |
Finding 1: omitted loader controls survive the shared environment filter and reach child processes. |
| A3 — Security / Privacy / Trust | CHANGES_REQUESTED |
Finding 1: project dotenv can cause loader-mediated code loading in an eligible child under the current user's authority. |
| A4 — Verification / Tests / CI | APPROVED |
Changed behavior has end-to-end and provenance tests; relevant exact-head CI checks passed. No separate test-only blocker. |
| A5 — Context / Compatibility / Platform | CHANGES_REQUESTED |
Finding 1 affects Linux/macOS loader behavior across bash consumers. The reuse check found no materially better existing abstraction. |
Limitations
The runtime intent_projection was unavailable. CI branch-protection settings could not be independently queried (GitHub returned 401), so this review reports observed check results rather than asserting configured requiredness. No local tests, builds, or platform runtime probes were run.
|
Approval remains held on The new peer review does not supply the missing verification: #6746 (review) . It requests changes for additional loader controls. That review remains unresolved; I have not dismissed it or independently reproduced its finding. The approval gate still returns
No approval or PR body change was made. The previous held review remains applicable: #6746 (review) . |
…ables from the bash spawn env
…rch-path overrides
|
Thanks @snowykr. Both loader paths reproduced and are fixed in On a stock Ubuntu 22.04 glibc, with
Added to the provenance-aware denylist:
Tests:
@probepark, your exact-head command record, run locally on
|
7b9e06b to
0366880
Compare
probepark
left a comment
There was a problem hiding this comment.
Review (head 0366880, gajae-reviewer on behalf of probepark)
Blocking: None found in step 3.
ocr: blocking 0 / nit 0
CI: Exact-head affected validation finished; the approval gate reports no pending or failed checks. The gate returned NEED_LOCAL (exit 11) for cd packages/coding-agent && bun run check. Need-local satisfied by the author's exact-head command and exit-0 record: #6746 (comment) . This is author-reported local evidence, not a command I ran.
Scope: +242 / -4, 6 files: utils spawn filtering, bash-path regressions, provenance tests, documentation, and a changelog fragment. OCR selected one production file (+11 / -3).
Conventions: Changelog fragment present; no released changelog edits, generated-file changes, or labels.
Notable:
packages/utils/src/shell-config.ts:76-97— The anchored denylist includes LD_AUDIT, LD_LIBRARY_PATH, and all six documented DYLD search overrides. Existing provenance checks still retain distinct inherited values and reject ambiguous project declarations.packages/coding-agent/src/exec/isolated-shell.ts:87-93,packages/coding-agent/src/exec/bash-executor.ts:451, andpackages/coding-agent/src/tools/bash-interactive.ts:328— Worker spawn, native environment stripping, and PTY unset names consume this shared filter. The shared shell-config environment and Python-kernel allowlist remain unchanged.- The loader omissions in the prior peer review are addressed at this head: #6746 (review) . That review belongs to the previous head. I have not dismissed another reviewer's review.
Verification: Exact-head CI ran bun scripts/ci-dev-affected.ts --task="$AFFECTED_TASK_KEY" for the bash-project-hook-env suite. Logs report 25 pass / 0 fail at 2026-10-14 12:47:59 UTC, including real LD_AUDIT and LD_LIBRARY_PATH payload tests and the trusted PYTHONPATH positive control. Job: https://github.com/Yeachan-Heo/gajae-code/actions/runs/38564398052/job/115860043646 . Utils check and spawn-env tests also passed. The author records exit 0 for both package checks at the full current SHA in the linked comment. No local builds or tests were run in this review environment.
Claim assessment: The denylist extension matches the PR's enumerated interpreter/loader scope. Existing tests were retained; new regressions exercise real subprocesses rather than module mocks.
Checked and clean: Production diff, shared provenance filter, three bash spawn paths, prior peer loader omissions, documentation, changelog placement, and exact-head Linux payload evidence.
Not assessed: Real macOS DYLD payload execution and intentionally excluded Ruby/interactive-Python vectors. This is not a complete sandbox boundary.
Verdict: gajae.pr-review-verdict.v1 merge-approved sha256:4d66aaaf6343f9da024aa0e5b7229821580a0e880f2490b4853837418d9b520d reviewer:human reviewer-id:probepark evidence:exact-head-linux-payload-tests-pass;loader-controls-covered;need-local-author-exit0
PR body verdict line count=0, not updated. Body is owned by 10kH; not edited. Suggested verdict line: gajae.pr-review-verdict.v1 merge-approved sha256:4d66aaaf6343f9da024aa0e5b7229821580a0e880f2490b4853837418d9b520d reviewer:human reviewer-id:probepark evidence:exact-head-linux-payload-tests-pass;loader-controls-covered;need-local-author-exit0
|
@snowykr friendly ping for a re-review of |
snowykr
left a comment
There was a problem hiding this comment.
Verdict
CHANGES_REQUESTED
Summary
The PR extends provenance-aware filtering for project-dotenv interpreter and loader hooks, but several distinct startup variables remain unfiltered. A repository-controlled .env can therefore still cause code to load during otherwise permitted Bash invocations.
Findings / Required Changes
-
[P1] Deny
JDK_JAVA_OPTIONSfrom project dotenv —packages/utils/src/shell-config.ts:72- Relative to the base, the new denylist adds
JAVA_TOOL_OPTIONSbut omits the Java launcher’s distinctJDK_JAVA_OPTIONSvariable. A project.envsetting such asJDK_JAVA_OPTIONS=-javaagent:/workspace/agent.jarsurvives the name filter; when a Bash command invokesjava, the launcher can execute that agent before the requested program. The worker, regular executor, and PTY paths all rely on this same filter, with no later removal. The added Java-agent test coversJAVA_TOOL_OPTIONS, not this separate launcher input. AddJDK_JAVA_OPTIONSto the provenance-aware denylist and cover it with a regression test while preserving a distinct trusted inherited value.
- Relative to the base, the new denylist adds
-
[P1] Deny Python user-site startup selectors —
packages/utils/src/shell-config.ts:72- The head adds
PYTHONPATHbut omitsPYTHONUSERBASEandPYTHONSTARTUP. When Python’s user site is enabled, a project.envcan pointPYTHONUSERBASEat repository-controlled packages containingusercustomize.py, which Python imports during startup. An interactive Python process started through the Bash PTY can also execute a project-selectedPYTHONSTARTUPfile. Both variables survive the central name filter; the worker, executor, and PTY consumers derive their filtering from that list. Add both names and regression coverage for the normal Python and interactive PTY paths. This is implicit code execution with the shell’s existing account authority, not an OS privilege escalation.
- The head adds
Non-blocking Observations
The new utils probe at packages/utils/test/shell-spawn-env-trust.test.ts:17-40,234-244 starts from process.env and clears only the older HOOK_KEYS, while asserting that newly covered variables are absent. If a runner exports one of those variables, the production provenance rule can correctly preserve that trusted inherited value and make the project-only assertion fail. Extend the probe cleanup list; this is a test-isolation issue, not an observed CI failure.
CI / Verification
Dev CI run 38564398052 is tied to the reviewed head. Affected-path validation, virtual integration validation, and the relevant coding-agent test, utils test, and utils check jobs succeeded. gh pr checks reported 20 successful and 13 skipped checks; the exact-SHA check-runs endpoint reported no failures (18 success, 12 skipped). Skips include opt-in or relevance-conditional jobs, not failed product tests. This review did not execute PR code or tests.
Axis Coverage
| Axis | Verdict | Coverage |
|---|---|---|
| A1 — Intent / Policy / Contract | CHANGES_REQUESTED |
Finding 1: the Java launcher startup hook remains project-controlled. |
| A2 — Architecture / Correctness / Failure | APPROVED |
Traced filtered environment copies and shared configuration through worker, executor, and PTY paths; no additional lifecycle or concurrency defect found. |
| A3 — Security / Privacy / Trust | CHANGES_REQUESTED |
Finding 2: Python startup mechanisms remain reachable from project dotenv values. |
| A4 — Verification / Tests / CI | APPROVED |
New tests exercise payload markers and provenance behavior; relevant exact-head jobs passed. The host-environment-dependent probe is noted above as non-blocking. |
| A5 — Context / Compatibility / Platform | APPROVED |
Consumers consistently use the existing provenance-aware abstraction; no materially preferable duplicate abstraction was identified. Platform-specific/opt-in skips are noted below. |
Limitations
WSLv2/DrvFS qualification was opt-in and skipped, and unrelated platform jobs were conditionally skipped. The findings are grounded in the shared filter and documented runtime startup behavior; no local runtime execution was performed.
Project dotenv startup variables can inject Python customization and Java agents into otherwise permitted Bash subprocesses. Extend provenance-aware filtering to these selectors while preserving distinct trusted inherited values, and exercise both real startup paths. Confidence: high Scope-risk: low Reversibility: easy Tested: bun test packages/utils/test/shell-spawn-env-trust.test.ts (21 passed) Tested: bun test packages/coding-agent/test/bash-project-hook-env.test.ts (26 passed, 2 skipped) Tested: bun --cwd=packages/utils run check Tested: bun --cwd=packages/coding-agent run check Not-tested: Java-agent runtime probes (JDK tools unavailable)
|
I preserved the PR author’s provenance-aware model: only project-provided values are stripped, while distinct trusted values exported by the launching shell remain available. Added regressions for The review was submitted in the review body rather than as inline comments; no unresolved inline review threads were returned, so this top-level reply summarizes the fix. — |
probepark
left a comment
There was a problem hiding this comment.
Code review (CI still running on 5332288; approval decision follows once CI finishes).
Review (head 5332288, gajae-reviewer on behalf of probepark)
Blocking: None found in step 3.
ocr: blocking 0 / nit 1
CI: Approval held. At 2026-10-15 16:12:07 UTC, python3 /opt/data/scripts/gajae-approve-gate.py 6746 --head 5332288b95b1e1c26edbde51e565b2a9022f05fa returned HOLD_CI (exit 10). Four pending items: darwin-arm64 tab-worker smoke, native-build, native addon, and the affected-path aggregate. No failures were reported. Run: https://github.com/Yeachan-Heo/gajae-code/actions/runs/38765046988 .
The gate also reports CI-plan gaps for cd packages/coding-agent && bun run check and cd packages/utils && bun run check. Recheck these after the affected plan finishes. The owner's comment reports package checks and 26 hook tests passing, with two Java cases skipped: #6746 (comment) . That comment does not include full-head command/exit records. It does not replace pending CI. No local builds or tests were run in this review environment.
Scope: +314 / -4, 6 files: utils spawn filtering, bash-path regressions, provenance tests, documentation, and a changelog fragment. OCR selected one production file (+12 / -3).
Conventions: Changelog fragment present; no released changelog edits, generated-file changes, or labels.
Notable:
packages/utils/src/shell-config.ts:72-93— The anchored denylist now coversJDK_JAVA_OPTIONS,PYTHONUSERBASE, andPYTHONSTARTUP, plus the earlier interpreter and loader controls. Existing provenance checks preserve distinct inherited values and reject ambiguous project declarations.packages/coding-agent/src/exec/isolated-shell.ts:85-91,packages/coding-agent/src/exec/bash-executor.ts:499-505, andpackages/coding-agent/src/tools/bash-interactive.ts:327-328— Worker spawning, native execution, and PTY unset names consume the shared filter. The shared shell-config environment remains unchanged.- The new regressions exercise real Java agents, Python user-site startup, interactive PTY startup, and loader payloads. The utils probe checks both dotenv autoload modes and distinct inherited values. Probe cleanup now includes the newly asserted variables.
Peer review: The omissions identified at the previous head are addressed in the current denylist and regression cases: #6746 (review) . That review remains CHANGES_REQUESTED; I have not dismissed another reviewer's review. No claim of peer approval is made.
Note: Update the description's “PYTHONSTARTUP is left out” statement. This head explicitly filters it and adds a PTY regression.
Claim assessment: The current code implements the documented provenance-aware interpreter/loader additions. Existing expectations are retained; new tests target real subprocess behavior, not module mocks.
Checked and clean: Production diff, provenance resolver, worker/native/PTY consumers, prior peer omissions, documentation, changelog placement, and test harness isolation.
Not assessed: Completed exact-head runtime CI, real macOS DYLD payload execution, and deliberately excluded Ruby hooks. This denylist is not a complete sandbox.
Verdict: Code-reviewed with blocking=0. Approval remains held for pending CI. PR body unchanged.
probepark
left a comment
There was a problem hiding this comment.
Approve held: CI plan did not run cd packages/coding-agent && bun run check on 5332288.
- Run
cd packages/coding-agent && bun run checkat5332288b95b1e1c26edbde51e565b2a9022f05fa. - Record the command, full head SHA, and exit code in a comment.
- Re-request review.
Blocking: No code findings. The completed exact-head code review remains applicable: #6746 (review) . This gate-only follow-up did not re-review the diff.
ocr: blocking 0 / nit 1
CI: gajae-approve-gate.py 6746 --head 5332288b95b1e1c26edbde51e565b2a9022f05fa returned NEED_LOCAL on 2026-10-15. It reports no pending or failed checks. Utils checks are covered. Coding-agent lint/typecheck is absent from the exact-head CI plan.
The owner's comment reports successful package checks: #6746 (comment) . It does not record the exact command, full head SHA, and exit code. The author's earlier exact-head command record applies to 036688007fe391cfa867f4f6b79d3649327d32ce, not this head. Neither record resolves the current verification gap. No local builds or tests were run in this review environment.
Peer review: The previous code review assessed the prior peer findings as addressed. No new peer review or human comment has appeared since that review. Another reviewer's CHANGES_REQUESTED review has not been dismissed.
Note: The description still says PYTHONSTARTUP is excluded, although this head filters it and adds a PTY regression.
Verdict: Approval held for missing verification, not a code defect. PR body unchanged.
snowykr
left a comment
There was a problem hiding this comment.
Verdict
APPROVED
Summary
This PR extends the existing provenance-aware filter for project-dotenv interpreter and dynamic-loader variables in Bash spawn environments. The exact-head consumers preserve distinct trusted launcher values and keep the policy scoped to Bash. No verified merge-blocking defect was found.
Findings / Required Changes
No blocking or actionable findings.
Non-blocking Observations
- The PR description says
PYTHONSTARTUPis excluded, but the exact-head filter includes it (packages/utils/src/shell-config.ts:73), with interactive Python coverage. Align the description with the implementation; this does not require a code change. - The Perl test sets project
PERL5OPTandPERL5LIBtogether. An optional assertion or scenario with trusted inheritedPERL5OPTand projectPERL5LIBwould catch a regression filtering only one key; the current implementation itself is correct.
CI / Verification
For reviewed head 5332288b95b1e1c26edbde51e565b2a9022f05fa, Dev CI and Public site sync succeeded, and all 21 PR checks were successful. Both changed test-file tasks passed. The opt-in WSLv2/NTFS qualification was skipped. No tests were run during this review.
Axis Coverage
| Axis | Verdict | Coverage |
|---|---|---|
| A1 — Intent / Policy / Contract | APPROVED |
Filter follows the existing provenance contract; PR-description discrepancy noted above. |
| A2 — Architecture / Correctness / Failure | APPROVED |
Existing filtering order and lifecycle remain unchanged; worker, native-shell, and PTY boundaries were traced. |
| A3 — Security / Privacy / Trust | APPROVED |
Project-origin values are filtered; trusted distinct inherited values remain intentional, with no new authority path. |
| A4 — Verification / Tests / CI | APPROVED |
Marker tests and env projection checks cover the change; per-key Perl coverage is an optional improvement. |
| A5 — Context / Compatibility / Platform | APPROVED |
POSIX, Windows, and PTY consumers were traced; Python REPL remains on its separate contract and no material duplicate abstraction was found. |
Limitations
Public CI evidence confirmed job outcomes, but detailed test-level pass/skip counts were unavailable.
probepark
left a comment
There was a problem hiding this comment.
Approval remains held on 5332288b95b1e1c26edbde51e565b2a9022f05fa.
The new peer approval resolves the prior peer objection: #6746 (review) . It states that no tests were run during that review. It does not supply the missing exact-head coding-agent check.
CI: The approval gate still returns NEED_LOCAL. It reports no pending or failed checks. Utils checks are covered. The head CI plan lacks cd packages/coding-agent && bun run check.
- Run
cd packages/coding-agent && bun run checkat5332288b95b1e1c26edbde51e565b2a9022f05fa. - Record the command, full head SHA, and exit code in a comment.
- Re-request review.
The owner's earlier comment reports successful package checks, but lacks the exact command, full head SHA, and exit code: #6746 (comment) . The author's explicit exit-0 record applies to an older head, not this one.
Blocking: No code findings in the completed exact-head review: #6746 (review) . This follow-up assesses the reply and verification gap; it does not re-review the diff.
ocr: blocking 0 / nit 1
Note: The description still says PYTHONSTARTUP is excluded, although this head filters it and adds a PTY regression.
Verdict: Reply evidence is insufficient to change the held decision. No local builds or tests were run here. No APPROVE, review dismissal, or PR body change.
|
Local check at exact head Exit code: 0. Biome: Checked 3550 files, no fixes applied. — |
What
This is the follow-up promised in #6559. It extends the bash tool's provenance-aware spawn-env denylist (
PROJECT_DENIED_SPAWN_ENVinpackages/utils/src/shell-config.ts) to interpreter and dynamic-loader injection variables:NODE_OPTIONS--require <file>in everynode(andnpm,npx, …)PYTHONPATHsitecustomize.pyon everypython3startPERL5OPT+PERL5LIB-M<Module>on everyperlstartJAVA_TOOL_OPTIONS-javaagent:<jar>premainbefore everyjavamainLD_PRELOADlsLD_AUDITla_versionin every dynamically linked commandLD_LIBRARY_PATHlibselinux.so.1forls)DYLD_INSERT_LIBRARIES,DYLD_{,FALLBACK_,VERSIONED_}{LIBRARY,FRAMEWORK}_PATHThe rule is unchanged from #6559 and from the owner's
BUN_OPTIONSaddition. A value is dropped only when it comes from the project.env. A distinct value the launching shell exported is kept, and ambiguous provenance fails closed. All spawn paths (isolated worker chain, in-process native shell, PTY) already go through the same filter, so this is a denylist and documentation change plus tests.Why
A repository's
.envshould not be able to make the bash tool run repository code. #6559 closed that for shell startup files and git hooks. The same.envcan still execute code through any interpreter or dynamically linked command the agent starts, which is most commands. I reproduced each vector through the realexecuteBashworker path on currentdev(9076fabf), both with Bun dotenv autoload and withbun --no-env-file(the compiled-binary condition):.env--no-env-file)NODE_OPTIONS=--require <proj>/r.jsnode -e 0PYTHONPATH=<proj>python3 -c 0PERL5OPT=-MpPERL5LIB=<proj>perl -e 0JAVA_TOOL_OPTIONS=-javaagent:<proj>/a.jarjava -versionLD_PRELOAD=<proj>/h.solsLD_AUDIT=<proj>/audit.solsLD_LIBRARY_PATH=<proj>/lib(filterlibselinux.so.1)lslsstill exits 0Baselines with no variable set: none of the payloads run. In particular, Python does not import a
sitecustomize.pyfrom the cwd unlessPYTHONPATHpoints at it.This follows the precedent in the repo:
gjc-runtime/ultragoal-evidence.ts:374already rejectsNODE_OPTIONS,LD_PRELOAD, andDYLD_*as command-hijacking env, andBUN_OPTIONSis on this same denylist.Not changed:
eval/py/runtime.ts) still forwardsPYTHONPATH. That is a documented, separate surface and the sharedgetShellConfig().envstays untouched, as in fix: keep project-dotenv shell and git hook variables out of the bash tool #6559.RUBYOPTandPYTHONSTARTUPare left out on purpose.PYTHONSTARTUPonly applies to interactive interpreters, and Ruby isn't on CI, so I couldn't add a real-path test for it.Testing
packages/coding-agent/test/bash-project-hook-env.test.ts(realexecuteBashworker path, payload marker oracle) adds:node+NODE_OPTIONS,python3+PYTHONPATH,perl+PERL5OPT/PERL5LIB. Each case skips if the interpreter is missing.java+JAVA_TOOL_OPTIONS, compiling a real agent jar. Skips without a JDK.ls+LD_PRELOAD,LD_AUDIT, andLD_LIBRARY_PATH, compiling a real constructor.so, an audit module, and a shadow filter library withcc. Linux only.PYTHONPATHthe launching shell exported still loads.packages/utils/test/shell-spawn-env-trust.test.ts:NODE_OPTIONS/PYTHONPATH/LD_PRELOADdeclarations are dropped in both autoload modes.LD_LIBRARY_PATH=/opt/cuda/lib64.shell-config.tsreverted todev, exactly the 9 new injection tests fail (7 E2E + 2 unit). With the change, they all pass: 46/46 across both suites.bun run checkpasses inpackages/utilsandpackages/coding-agent.bun scripts/changelog-fragments.ts checkpasses.Approval
Merges to
devrequire one approving GitHub review from a write-access maintainer on the current head. Agent reviews (architect/critic) are advisory comments.devbun checkpassespackages/<pkg>/changelog.d/(if user-facing)