Skip to content

fix(utils): keep project-dotenv interpreter and loader injection variables out of the bash tool - #6746

Merged
Yeachan-Heo merged 4 commits into
Yeachan-Heo:devfrom
10kH:fix/project-dotenv-runtime-injection
Oct 15, 2026
Merged

Yeachan-Heo merged 4 commits into
Yeachan-Heo:devfrom
10kH:fix/project-dotenv-runtime-injection

Conversation

@10kH

@10kH 10kH commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What

This is the follow-up promised in #6559. It extends the bash tool's provenance-aware spawn-env denylist (PROJECT_DENIED_SPAWN_ENV in packages/utils/src/shell-config.ts) to interpreter and dynamic-loader injection variables:

Variable Code it runs
NODE_OPTIONS --require <file> in every node (and npm, npx, …)
PYTHONPATH sitecustomize.py on every python3 start
PERL5OPT + PERL5LIB -M<Module> on every perl start
JAVA_TOOL_OPTIONS -javaagent:<jar> premain before every java main
LD_PRELOAD a shared-library constructor in every dynamically linked command, including ls
LD_AUDIT an audit module's la_version in every dynamically linked command
LD_LIBRARY_PATH a project library shadowing a system one (e.g. libselinux.so.1 for ls)
DYLD_INSERT_LIBRARIES, DYLD_{,FALLBACK_,VERSIONED_}{LIBRARY,FRAMEWORK}_PATH the macOS equivalents

The rule is unchanged from #6559 and from the owner's BUN_OPTIONS addition. 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 .env should not be able to make the bash tool run repository code. #6559 closed that for shell startup files and git hooks. The same .env can still execute code through any interpreter or dynamically linked command the agent starts, which is most commands. I reproduced each vector through the real executeBash worker path on current dev (9076fabf), both with Bun dotenv autoload and with bun --no-env-file (the compiled-binary condition):

.env Command run by the bash tool Payload ran (autoload / --no-env-file)
NODE_OPTIONS=--require <proj>/r.js node -e 0 yes / yes
PYTHONPATH=<proj> python3 -c 0 yes / yes
PERL5OPT=-Mp PERL5LIB=<proj> perl -e 0 yes / yes
JAVA_TOOL_OPTIONS=-javaagent:<proj>/a.jar java -version yes (direct)
LD_PRELOAD=<proj>/h.so ls yes, 15 constructor hits per command / same
LD_AUDIT=<proj>/audit.so ls yes
LD_LIBRARY_PATH=<proj>/lib (filter libselinux.so.1) ls yes, ls still exits 0

Baselines with no variable set: none of the payloads run. In particular, Python does not import a sitecustomize.py from the cwd unless PYTHONPATH points at it.

This follows the precedent in the repo: gjc-runtime/ultragoal-evidence.ts:374 already rejects NODE_OPTIONS, LD_PRELOAD, and DYLD_* as command-hijacking env, and BUN_OPTIONS is on this same denylist.

Not changed:

  • The Python REPL kernel's own allowlist (eval/py/runtime.ts) still forwards PYTHONPATH. That is a documented, separate surface and the shared getShellConfig().env stays untouched, as in fix: keep project-dotenv shell and git hook variables out of the bash tool #6559.
  • RUBYOPT and PYTHONSTARTUP are left out on purpose. PYTHONSTARTUP only 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 (real executeBash worker 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, and LD_LIBRARY_PATH, compiling a real constructor .so, an audit module, and a shadow filter library with cc. Linux only.
    • A positive case: a PYTHONPATH the launching shell exported still loads.
  • packages/utils/test/shell-spawn-env-trust.test.ts:
    • Project NODE_OPTIONS/PYTHONPATH/LD_PRELOAD declarations are dropped in both autoload modes.
    • Distinct operator values are kept, including LD_LIBRARY_PATH=/opt/cuda/lib64.
  • Reverse check: with shell-config.ts reverted to dev, exactly the 9 new injection tests fail (7 E2E + 2 unit). With the change, they all pass: 46/46 across both suites.
  • Regression: 723 tests across the bash, utils, PTY, interceptor, and Python-kernel env suites. Diffed before/after, no new failures.
  • bun run check passes in packages/utils and packages/coding-agent. bun scripts/changelog-fragments.ts check passes.

Approval

Merges to dev require one approving GitHub review from a write-access maintainer on the current head. Agent reviews (architect/critic) are advisory comments.


  • Target branch is dev
  • bun check passes
  • Tested locally
  • Changelog fragment added under packages/<pkg>/changelog.d/ (if user-facing)
  • Human approval or the required agent/owner verdict matches the exact PR head, not an earlier commit
  • Risk classification above matches the actual review path taken

@probepark probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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-451 and packages/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 call projectSafeSpawnEnv.
  • 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 probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

  1. [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_PRELOAD and DYLD_INSERT_LIBRARIES; the new denylist still omits LD_AUDIT, LD_LIBRARY_PATH, and DYLD search-path overrides such as DYLD_LIBRARY_PATH and DYLD_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 .env setting LD_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 treats LD_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_AUDIT and 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.

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.

@probepark

Copy link
Copy Markdown
Collaborator

Approval remains held on 7b9e06b2c025b383c9de72e089c9950485056dcd.

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 NEED_LOCAL (exit 11). It reports no pending or failed CI checks, but lacks the coding-agent lint/typecheck command.

  1. Run cd packages/coding-agent && bun run check at this exact head.
  2. Record the command, full head SHA, and exit code in a comment.
  3. Answer the peer review's loader-control finding and re-request review.

No approval or PR body change was made. The previous held review remains applicable: #6746 (review) .

@10kH

10kH commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @snowykr. Both loader paths reproduced and are fixed in 03668800.

On a stock Ubuntu 22.04 glibc, with ls as the command:

  • LD_AUDIT=<proj>/audit.so (an audit module exporting la_version): the loader called the module, 1 marker hit per command.
  • LD_LIBRARY_PATH=<proj>/lib, holding a libselinux.so.1 built as an ELF filter on the real library: the planted constructor ran and ls still exited 0.

Added to the provenance-aware denylist: LD_AUDIT, LD_LIBRARY_PATH, and the macOS search overrides DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH, DYLD_FRAMEWORK_PATH, DYLD_FALLBACK_FRAMEWORK_PATH, DYLD_VERSIONED_LIBRARY_PATH, DYLD_VERSIONED_FRAMEWORK_PATH. Docs, the source comment, and the changelog fragment are updated.

LD_LIBRARY_PATH is commonly exported by operators (CUDA, conda). The provenance rule keeps a distinct launcher value, and the unit suite now asserts that (LD_LIBRARY_PATH=/opt/cuda/lib64 kept while the project declares ./lib).

Tests:

  • Real executeBash worker path: LD_AUDIT and LD_LIBRARY_PATH vectors, each compiling the real module or shadow library with cc (Linux).
  • Unit: LD_AUDIT, LD_LIBRARY_PATH, and DYLD_LIBRARY_PATH are dropped in both autoload modes.
  • Against the previous head 7b9e06b, exactly those 4 fail. On this head, 46/46 pass.
  • Regression: 723 tests across the bash, utils, PTY, interceptor, and Python-kernel env suites, with no new failures.

@probepark, your exact-head command record, run locally on 036688007fe391cfa867f4f6b79d3649327d32ce after a native rebuild:

  • cd packages/coding-agent && bun run check → exit 0
  • cd packages/utils && bun run check → exit 0

@10kH
10kH force-pushed the fix/project-dotenv-runtime-injection branch from 7b9e06b to 0366880 Compare October 14, 2026 12:30
probepark
probepark previously approved these changes Oct 14, 2026

@probepark probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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, and packages/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

@Yeachan-Heo
Yeachan-Heo requested a review from snowykr October 14, 2026 23:40
@10kH

10kH commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

@snowykr friendly ping for a re-review of 03668800. LD_AUDIT, LD_LIBRARY_PATH, and the DYLD search-path overrides from your finding are covered (details in the comment above). probepark approved this head, and exact-head CI is green (20 pass).

@snowykr snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

  1. [P1] Deny JDK_JAVA_OPTIONS from project dotenv — packages/utils/src/shell-config.ts:72

    • Relative to the base, the new denylist adds JAVA_TOOL_OPTIONS but omits the Java launcher’s distinct JDK_JAVA_OPTIONS variable. A project .env setting such as JDK_JAVA_OPTIONS=-javaagent:/workspace/agent.jar survives the name filter; when a Bash command invokes java, 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 covers JAVA_TOOL_OPTIONS, not this separate launcher input. Add JDK_JAVA_OPTIONS to the provenance-aware denylist and cover it with a regression test while preserving a distinct trusted inherited value.
  2. [P1] Deny Python user-site startup selectors — packages/utils/src/shell-config.ts:72

    • The head adds PYTHONPATH but omits PYTHONUSERBASE and PYTHONSTARTUP. When Python’s user site is enabled, a project .env can point PYTHONUSERBASE at repository-controlled packages containing usercustomize.py, which Python imports during startup. An interactive Python process started through the Bash PTY can also execute a project-selected PYTHONSTARTUP file. 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.

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.

clawdbot added 2 commits October 15, 2026 15:42
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)
@Yeachan-Heo

Copy link
Copy Markdown
Owner

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 JDK_JAVA_OPTIONS, PYTHONUSERBASE, and PYTHONSTARTUP, including Java-agent startup, Python usercustomize.py, and PYTHONSTARTUP through the interactive PTY. The utils trust test and both package checks pass. The coding-agent hook test passed (26 passed; two Java-agent cases skipped because java, javac, and jar are unavailable). The coding-agent check reported only its existing large-file warning for src/session/agent-session.ts.

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.

—
[repo owner's gaebal-gajae (clawdbot) 🦞]

@probepark probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 covers JDK_JAVA_OPTIONS, PYTHONUSERBASE, and PYTHONSTARTUP, 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, and packages/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 probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approve held: CI plan did not run cd packages/coding-agent && bun run check on 5332288.

  1. Run cd packages/coding-agent && bun run check at 5332288b95b1e1c26edbde51e565b2a9022f05fa.
  2. Record the command, full head SHA, and exit code in a comment.
  3. 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 snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 PYTHONSTARTUP is 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 PERL5OPT and PERL5LIB together. An optional assertion or scenario with trusted inherited PERL5OPT and project PERL5LIB would 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 probepark left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.

  1. Run cd packages/coding-agent && bun run check at 5332288b95b1e1c26edbde51e565b2a9022f05fa.
  2. Record the command, full head SHA, and exit code in a comment.
  3. 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.

@Yeachan-Heo

Copy link
Copy Markdown
Owner

Local check at exact head 5332288b95b1e1c26edbde51e565b2a9022f05fa (Linux x86_64, Bun, bun install --frozen-lockfile in a clean worktree):

cd packages/coding-agent && bun run check

Exit code: 0. Biome: Checked 3550 files, no fixes applied. generate-docs-index + tsc -p tsconfig.json --noEmit passed, and the worktree stayed clean afterward.

—
[repo owner's gaebal-gajae (clawdbot) 🦞]

@Yeachan-Heo
Yeachan-Heo merged commit 0d570b7 into Yeachan-Heo:dev Oct 15, 2026
28 checks passed
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.

4 participants