Repository navigation
#659 [security][tools] workflow の子 node の隔離の照合、run の一時ディレクトリの後片付け、mktemp の案内 - #665
Merged
Kewton merged 4 commits intoOct 13, 2026
Conversation
… workspace When a workflow child node runs in a workspace other than the run's, the installed OS write sandbox is fixed to the run's workspace. Instead of applying it to the wrong workspace, record it as not applied for that node: `auto` continues with lexical checks only and `required` fails the node's Bash and verifier commands, so a node is never recorded as isolated while Bash runs in a different workspace. When the workspace matches, nothing changes. Once a mismatch is recorded, it does not revert when a later node runs in the parent's workspace; the stricter record is kept. Skip installing the sandbox (and its per-run temp directory) for read-only actions, and remove the run temp directory on every exit path. The direct-CLI SIGINT finalizer exits with `std::process::exit`, which skips `Drop`, so it releases the run temp directory itself before both of its exits (the summary path and the already-finalized path). Append a `mktemp -p "$TMPDIR"` hint to a Bash failure summary when the sandbox is applied and the failure is a temp-directory permission error. Document in SECURITY.md that runtime dependency setup runs outside the sandbox and that a workspace hardlink that pre-exists the run can be written through. 判断: Issue #659 leaves the child-node fix open (re-point the sandbox to the child workspace, or record applied=false and fail under `required`). Chose the second, smaller option: it needs no new temp directory and no profile rebuild, and keeps the call site a single reconcile step. `auto` continues with lexical checks only and `required` fails, so the record never claims isolation that was not in force. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
`cleanup()` removed the policy but left `availability = Available`, so
`is_applied()` stayed true and `wrap_command` passed a command through unwrapped
under `required`. A child spawned between the guard drop, or the SIGINT
finalizer's cleanup and `exit(130)`, could then run unconfined while the record
still claimed the sandbox was applied. `cleanup()` now also moves an applied
sandbox to `Unavailable("run finished")`, and `wrap_command` refuses under
`required` when the backend is available but no policy is installed.
Chose "mark unavailable on cleanup" over "keep the policy": it is the smaller
change, leaves `auto`/`off` untouched, and avoids handing children a policy whose
run temp directory was just deleted. The `wrap_command` refusal hardens the
policy-missing branch so the invariant cannot silently regress.
Test: cleanup_ends_the_run_without_leaving_the_sandbox_applied (Required +
Available via install_for_test, then cleanup) fails on 4dc2162 and passes now.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Cover the branch where the backend is available but the run's policy is gone: `required` refuses with `bash_sandbox_unavailable` and `auto` continues as before. The applied integration test cannot reach this branch because `cleanup` also marks the sandbox unavailable, so cargo mutants' `==` -> `!=` mutation in that branch went uncaught. The tests set `INSTALLED` directly under the module's existing serialized test state, so no production API or field is added. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Closed
10 tasks
Kewton
deleted the
feature/issue-659-security-tools-1a-workflow-node-mktemp-run
branch
October 13, 2026 01:22
5 tasks
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.
概要
書き込み隔離(1a、#655)の後続です。workflow の子 node の隔離を照合して正直に記録し、run の一時ディレクトリを終了時に片付け、隔離の中で
mktempが失敗したときに案内を出します。merge 前レビュー(H-25)で見つかった P1(cleanup()の後にrequiredでも素通しになる)も、この PR で直しています。Refs #659
変更(develop 比 5 ファイル、+570 −27)
src/tools/os_sandbox.rsのreconcile_workspace、src/lib.rsのrun_resolved_config_for_workflow)Unavailable("workflow node runs in a workspace other than the run workspace; …")にし、applied=falseで記録します。requiredでは、Bash と検証のコマンドを拒否します(既存のwrap_commandの Unavailable の分岐)。同じワークスペースなら何もしません。cleanup・SandboxCleanupGuard・cleanup_guardを足しました。成功と失敗は drop guard で、中断は SIGINT の finalizer(finalize_interrupted_direct_command)で、exit(130)の前にcleanup()を呼びます。--runs・--ux-demo・--model-probe・--doctor)では、隔離の設定も一時ディレクトリの作成もしません。cleanup()の後にrequiredで素通しにしない(H-25 の P1)cleanup()は、隔離が適用中なら availability をUnavailable("run finished; …")に変えてから、policy を外してディレクトリを消します。cleanup の後はis_applied()が false です。wrap_commandの「Availableかつ policy が None」の分岐は、requiredでは拒否します(autoは従来どおり)。availability と policy を別の lock で読む間にcleanupが入る競合も、この分岐が受けます。auto・offに触れず、消したばかりの一時ディレクトリを指す policy を子に渡さないため、この方法を選びました。mktempの案内(src/tools/bash.rs):隔離が適用されていて、失敗が一時ディレクトリの権限エラーのときだけ、要約にmktemp -p "$TMPDIR"の案内を足します。判定と許可は変えていません。SECURITY.md:「What remains lexical-only」に、依存の導入が隔離の外であること([security][tools]--offlineの外向きの通信を OS の隔離で遮断し、runtime の依存の導入を隔離の中で動かす(第 3 段) #658)と、事前にある外向きの hardlink の限界を追記しました。tests/issue502_os_sandbox_write.rsは 10 本から 18 本になりました。os_sandboxの単体試験も 2 本足しています。macOS 専用の helper は cfg で囲みました。allow(dead_code)は 0 行です。reasonの文字列が 2 つ増えただけ)、成長上限のファイルと baseline。検証(HEAD
6c4e6f91、develop6b264fabを取り込み済み)commandmate verifyで 15/15 passed。cargo-zigbuild clippy --all-targets --target x86_64-unknown-linux-gnuは exit 0(warning・error 0)でした。--include-ignored):18/18 pass、SKIP 0。target が checkout の下にある配置でも 17/17 pass でした(P1 の修正の前、L-32 の時点)。936dbd37に新しい試験を置くと compile error になります(reconcile_workspace・cleanupが無い)。cleanup_ends_the_run_without_leaving_the_sandbox_appliedは、修正の前の4dc21624で落ちます(17 passed・1 failed)。--jobs 1、--timeout 300、RUSTFLAGS="-A unused-variables")build_summaryの行、4 件は案内の語の||です。requiredの判定の反転が missed だったので、単体試験を足して捕まえました。Defaultを持たない型への置き換えで、build できない変異です。レビュー
requiredは cleanup の前はsandbox-execで包まれ、後は拒否されます。autoの許可は増えていません。offは変わりません。autoで、ワークスペースの違う子 node は隔離なしで走ります。記録は正直なので、今のままとしました。node ごとに profile を作り直すかは、1b([security][tools] Bash と検証コマンドの書き込みを Linux の landlock で閉じ込める(第 1 段 b) #656)で検討します。applied=falseになると戻りません。厳しい側で正直なので、今のままとしました。--origin ≠ --workspaceの 2 node の workflow を mock provider で通し、子の events にapplied=falseがあることを確かめる試験を、後続で 1 本足すことを推奨されています。cleanup()の cfg:今のままとしました。確かめてほしい点
reconcile_workspaceを直接呼ぶ形です。workflow を通しで走らせる試験は、上の c のとおり後続に残しています。cleanup()の後は、autoでもis_applied()が false になります。bash_sandbox_statusを出すのは run の開始時だけなので、cleanup の後に出る event はありません。requiredの「policy が None」の拒否は、ほとんどの場合 cleanup が先にUnavailableにするので届きません。lock の間の競合だけで届く防御の分岐で、単体試験で固定しています。🤖 Generated with Claude Code