Repository navigation
fix(pr-review): install sandbox-runtime's seccomp helper for the lanes - #1029
Conversation
Claude Code 2.1.304 and later pass bubblewrap --disable-userns when no apply-seccomp helper is found. That flag writes /proc/sys/user/max_user_namespaces, which Docker mounts read-only on the melodic-review workers, so every Bash call in a review lane fails. The isolation step in both lanes now downloads the pinned @anthropic-ai/sandbox-runtime 0.0.81 tarball from the npm registry, checks its SHA-256, and installs only the helper, root-owned, under /usr/local/lib/node_modules, a root sandbox-runtime searches. The worker image has no npm, so this needs no Node toolchain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XWwmbdW8moDiQ5Rtgt7d5
Codex Review Summary: ❌ FailedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
claude-security-review reviewed Security review: incremental, d8087e5I found no security issues in this change. I reviewed only the diff since eeb4684 in What changed: the "Install subprocess isolation" step used to fail the lane if the seccomp helper ( Checks:
manifest fields: none touched. |
|
claude-review reviewed Review (incremental, since eeb4684)No findings. I read the incremental diff and the surrounding step and test at head. I did not run the tests myself. What changed. The seccomp-helper install in What I checked
Advisory, not counted as findings
Closing issues. The PR uses |
|
PR body contract — issue linkage This PR body conforms to the issue-linkage contract. Nothing to do. |
A failed download, a hash mismatch, an unsupported architecture or a failed extract now installs nothing, warns with the cause, and lets the isolation step continue. Without the helper Claude Code behaves as it did before, so a registry outage no longer stops every review lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XWwmbdW8moDiQ5Rtgt7d5
Refs: #938
Summary
The Claude review lanes on the melodic-review Docker workers have no working shell. Every Bash call fails with
bwrap: cannot open /proc/sys/user/max_user_namespaces: Read-only file system. This PR installs sandbox-runtime'sapply-seccomphelper in both lanes. With the helper present, Claude Code no longer asks bubblewrap for--disable-userns.The CI Runner session found the cause in ci-runner#528 (comment). I re-read each cited source line myself, at the versions concerned:
--disable-usernsopens the sysctl for writing and dies when it cannot. bubblewrap.c:3395-3402 at 1fb0aa2:apply-seccomp binary not available - unix socket blocking disabled. Install @anthropic-ai/sandbox-runtime globally for full protection.findGlobalApplySeccompPath(getGlobalNpmPaths())(generate-seccomp-filter.ts:202-206). That joins<root>/vendor/seccomp/<arch>/apply-seccomp(L283-L299). The roots arenpm root -gplus static paths that includejoin('/usr', 'local', 'lib', 'node_modules', '@anthropic-ai', 'sandbox-runtime')(L76-L97). Claude Code's sandboxing docs say the same: "Install it withnpm install -g @anthropic-ai/sandbox-runtimeif it is missing."src/entrypoints/run.tsfromconst claudeCodeVersion = "2.1.303";to"2.1.304". I counted the string--disable-usernsin each@anthropic-ai/claude-code-linux-x64binary from the npm registry: 2.1.303 has 0, 2.1.304 has 3, and 2.1.319 has 3. 2.1.319 is the version the latest release, v1.0.269, installs (run.ts:80at 61a9c27).linux-sandbox-utils.ts,generate-seccomp-filter.tsorapply-seccomp.c. The behavior came in with sandbox-runtime#588, merged 2026-10-14, before v0.0.80. The v0.0.81 helper binary carriesSRT_ALLOW_NESTED_USERNS, the variable Claude Code's bundled runtime sets in front of it.Fix
The
Install subprocess isolationstep inpr-review.ymlandpr-review-security.ymlnow does the following. The two copies stay byte-identical, and the existing test holds them equal.https://registry.npmjs.org/@anthropic-ai/sandbox-runtime/-/sandbox-runtime-0.0.81.tgz, the latest stable release (npm viewdist-tagslatest: 0.0.81, published 2026-10-20).0e0b8249…953f. Integrity follows the repo's pinned-download pattern (.github/actions/_shared/install-release.sh). I checked the pinned artifact three ways:dist.integrity(sha512-bjHDu87g…W/w==).npm audit signatureson an install of 0.0.81 reports "5 packages have verified registry signatures" and "2 packages have verified attestations".package/vendor/seccomp/<arch>/apply-seccomp. The binary is statically linked. It installs the binary root-owned, mode 0755, at/usr/local/lib/node_modules/@anthropic-ai/sandbox-runtime/vendor/seccomp/<arch>/apply-seccomp.Why not
npm install -g: the worker image has no npm. ci-runner's docs/worker-image.md says "node,npm,npx) are absent from PATH so workflows must install them with their official setup actions". A global npm install would need a setup-node step, which would put Node in the model's Bash environment, and it would pull four caret-ranged dependencies the helper does not use. The static/usr/local/libroot is searched whether or not npm is on PATH.The step timeout goes from 1 to 2 minutes. The download is bounded at 3 attempts of 15 s, so the apt deadline (50 s) plus the download still fits. The helper install is best-effort. A failed download, a SHA-256 mismatch, an unsupported architecture or a failed extract installs nothing and emits a
::warning::that names the cause. The step then continues, so a registry outage cannot stop a lane. Without the helper, Claude Code behaves as it does today. A binary that failed its hash is never installed.Left out:
pr-review-cli.yml. Its model has Bash disallowed (header, lines 120-123: "Bash and the write and web tools are disallowed"), so no sandboxed command runs there.Verification
After the best-effort change,
node --teston.github/scripts/claude-*.test.cjs,lane-outcome-emitters.test.cjsandpr-review-cli.test.cjs: 333 pass, 0 fail.Two new tests in
claude-lane-install-isolation.test.cjsrun the step's own script with stubcurlandsudo:sudo install -D -o root -g root -m 0755, from the 0.0.81 registry URL.Each test failed when I broke the code on purpose: the helper path moved to
/opt/tools, and the SHA-256 check turned off.I ran the step's script against the live registry with the real pin, with only
sudostubbed. It exited 0. The installed helper's SHA-256 (7effeb0f…ca24a) equals the one in a plainnpm packof 0.0.81.actionlint(only the known$/noise),zizmor --offline(no findings) andbiome cion the test: clean.Not yet verified: a review lane on a melodic-review worker with
SRT_DEBUG=1on the latest claude-code-action. That run would show bwrap starting without--disable-userns, Bash calls succeeding, and whether the helper's nested unshare passes ci-runner'susernsseccomp profile. pr-pipeline-sandbox cannot run it: the repository is public, and every org runner group hasallows_public_repositories: false(runner groups 4 and 5 list only private repositories). Until that run passes, the claude-code-action v1.0.253 pin and the Dependabot ignore at.github/dependabot.yml:34stay, and the issue stays open. When the pin is lifted, note that v1.0.269 is inside the 3-day Dependabot cooldown until 2026-11-09.Related
🤖 Generated with Claude Code
https://claude.ai/code/session_015XWwmbdW8moDiQ5Rtgt7d5