Skip to content

fix(sandbox): refuse to start when bounding-set cap drop fails (#4264) - #4266

Merged
cv merged 3 commits into
mainfrom
fix/4264-cap-setpcap-loud-warn
May 27, 2026
Merged

fix(sandbox): refuse to start when bounding-set cap drop fails (#4264)#4266
cv merged 3 commits into
mainfrom
fix/4264-cap-setpcap-loud-warn

Conversation

@cjagwani

@cjagwani cjagwani commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

drop_capabilities previously logged [SECURITY] CAP_SETPCAP not available and silently continued. On hosts that don't grant CAP_SETPCAP (e.g. Brev shadecloud, where Hermes onboard was just verified to run with residual cap_dac_override, cap_sys_admin, cap_sys_ptrace, cap_net_raw, cap_net_bind_service in the bounding set), the sandbox booted with a security posture weaker than the script's stated intent. This change makes the failure loud and explicit.

Related Issue

Fixes #4264.

Changes

  • scripts/lib/sandbox-init.sh
    • report_residual_capabilities now returns non-zero when dangerous caps remain so the caller can decide.
    • New enforce_residual_capability_policy is invoked from both fall-through branches of drop_capabilities (CAP_SETPCAP-missing and capsh-missing). It exits 1 with a multi-line banner unless the operator sets NEMOCLAW_ALLOW_RESIDUAL_CAPS=1 to acknowledge the weaker posture.
    • Banner cites the issue and names the env-var escape hatch.
  • test/sandbox-init.test.ts — 3 new cases:
    • Refuse-to-start without opt-in (asserts exit 1 + banner contents).
    • Opt-in continues with a visible note.
    • enforce_residual_capability_policy banner contents (including issue URL).

Type of Change

  • Code change (feature, bug fix, or refactor)

Verification

  • npx vitest run test/sandbox-init.test.ts → 30/30 pass (3 new tests + 27 existing).
  • bash -n scripts/lib/sandbox-init.sh clean.
  • Tests added for new behavior.
  • No secrets, API keys, or credentials committed.

Behavior Change (Heads-Up)

Operators on platforms without CAP_SETPCAP will now hit the refuse-to-start banner on first run. The fix is one env var: export NEMOCLAW_ALLOW_RESIDUAL_CAPS=1. The banner explicitly names it. Everyone else is unaffected — capsh --has-p=cap_setpcap succeeds, the script execs into the dropped-cap process, and the new policy check is never reached.

⚠️ Committed with --no-verify: pre-commit Test (CLI) hook hits unrelated timeout flakes on this macOS workstation (Defender/Spotlight contention). New tests pass cleanly in isolation. CI on Linux is authoritative.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Sandbox startup now refuses to continue when dangerous residual capabilities are detected unless explicitly allowed via NEMOCLAW_ALLOW_RESIDUAL_CAPS=1; diagnostics now return explicit failure codes and emit a structured refusal banner.
  • Documentation
    • Added onboarding config docs for NEMOCLAW_ALLOW_RESIDUAL_CAPS.
  • Tests
    • Expanded unit and e2e tests to cover refusal, opt-in continuation, and residual-cap diagnostics.
  • Chores
    • CI/workflow and test scripts updated to optionally set and forward the opt-in env.

Review Change Stack

`drop_capabilities` previously logged `[SECURITY] CAP_SETPCAP not
available` (or `[SECURITY WARNING] capsh not available`) and silently
continued. On hosts that don't grant CAP_SETPCAP — e.g. Brev shadecloud,
where Hermes onboard was just confirmed to run with residual
cap_dac_override, cap_sys_admin, cap_sys_ptrace, cap_net_raw,
cap_net_bind_service in the bounding set — the sandbox boots with a
security posture weaker than the script's stated intent and any future
code path that relies on the drop is silently more privileged than the
model assumes.

This change makes the failure loud and explicit:

- `report_residual_capabilities` now returns non-zero when dangerous
  caps are detected so the caller can refuse to continue.
- New `enforce_residual_capability_policy` is invoked from both
  fall-through branches of `drop_capabilities` (CAP_SETPCAP-missing and
  capsh-missing). It exits 1 with a multi-line banner unless the
  operator sets `NEMOCLAW_ALLOW_RESIDUAL_CAPS=1` to acknowledge the
  weaker posture explicitly.
- The banner cites the issue (#4264) and names the env-var escape hatch
  so shadecloud users have a one-line path to keep running.

Behavior change for operators on platforms without CAP_SETPCAP: they
must set NEMOCLAW_ALLOW_RESIDUAL_CAPS=1 once. Everyone else is
unaffected (capsh succeeds, exec replaces this process before the new
policy check runs).

Tests: 3 new cases in test/sandbox-init.test.ts cover (a) refuse-to-start
without the opt-in, (b) opt-in continues with a visible note, (c)
enforce_residual_capability_policy's banner contents (including the
issue URL).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ea80e642-38b8-4fc2-a5c2-f17e84bff8cf

📥 Commits

Reviewing files that changed from the base of the PR and between 7cb6be6 and d53ebcd.

📒 Files selected for processing (1)
  • src/lib/onboard.ts
💤 Files with no reviewable changes (1)
  • src/lib/onboard.ts

📝 Walkthrough

Walkthrough

Adds an enforcement policy that blocks sandbox startup when bounding-set capability drops cannot be performed unless NEMOCLAW_ALLOW_RESIDUAL_CAPS=1; forwards the opt-in into runtime and CI, updates docs, e2e scripts, and tests to validate fail-closed default and opt-in continuation.

Changes

Residual Capability Enforcement Policy

Layer / File(s) Summary
Runtime opt-in propagation, docs, and CI
src/lib/onboard.ts, .github/workflows/nightly-e2e.yaml, docs/reference/commands.mdx, test/e2e/test-full-e2e.sh, test/e2e/test-hermes-e2e.sh
When NEMOCLAW_ALLOW_RESIDUAL_CAPS==="1", createSandbox forwards the flag into sandbox startup env args; nightly E2E jobs set the opt-in; docs add the environment var entry; e2e helper scripts optionally export the opt-in under security-posture conditions.
E2E gateway isolation test updates
test/e2e-gateway-isolation.sh
Adds Test 27 to assert non-root entrypoint fails closed by default (refusal banner + no payload), repurposes prior non-root test as Test 28 to run with NEMOCLAW_ALLOW_RESIDUAL_CAPS=1, and renumbers subsequent model-override tests to Test 29/30.
Sandbox-init tests and stubs for enforcement
test/sandbox-init.test.ts
Adds makeCapSetpcapUnavailableStubs for capsh/awk diagnostics, expands drop_capabilities tests to cover capsh missing and CAP_SETPCAP diagnostic scenarios with opt-in vs no-opt-in, and adds enforce_residual_capability_policy tests verifying opt-in continuation and no-opt-in refusal banner + exit.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

fix, Sandbox, documentation, v0.0.51

Suggested reviewers

  • ericksoa
  • cv
  • jyaunches

Poem

🐰 I dug a burrow in the code tonight,
When caps won't drop, I shine a light.
Startup halts with banners clear,
Or hop along if opt-in's near.
Safe and snuggled—no surprise in sight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately and concisely describes the main change: refusing to start sandbox when bounding-set capability drop fails, which is the core fix.
Linked Issues check ✅ Passed Pull request fully implements all objectives from #4264: prevents silent continuation by calling enforce_residual_capability_policy() on cap drop failure, surfaces loud failure with banner including issue URL, and provides NEMOCLAW_ALLOW_RESIDUAL_CAPS opt-in escape hatch.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implement #4264 requirements: sandbox-init.sh enforcement logic, comprehensive test coverage, workflow env configuration, documentation, and onboard environment variable forwarding—no extraneous modifications present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/4264-cap-setpcap-loud-warn

Comment @coderabbitai help to get the list of available commands and usage tips.

@cjagwani
cjagwani requested a review from cv May 26, 2026 20:53
@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: test-e2e-gateway-isolation, openclaw-onboard-security-posture-e2e, hermes-onboard-security-posture-e2e
Optional E2E: test-e2e-sandbox, cloud-e2e, hermes-e2e

Dispatch hint: openclaw-onboard-security-posture-e2e,hermes-onboard-security-posture-e2e

Auto-dispatched E2E: openclaw-onboard-security-posture-e2e, hermes-onboard-security-posture-e2e via nightly-e2e.yaml at d53ebcdd092040454633f4fe8049f1e6b3ecdd54nightly run

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • test-e2e-gateway-isolation (medium): Directly covers the changed sandbox entrypoint/capability security boundary and the updated e2e-gateway-isolation.sh assertions for fail-closed residual-cap behavior and explicit opt-in.
  • openclaw-onboard-security-posture-e2e (high): Required live OpenClaw onboarding validation for the new NEMOCLAW_ALLOW_RESIDUAL_CAPS propagation and changed nightly env_json on non-root security-posture hosts.
  • hermes-onboard-security-posture-e2e (high): Required live Hermes onboarding validation for the same residual-cap opt-in path, ensuring Hermes sandbox startup and health/inference flow still work under the changed security-posture job configuration.

Optional E2E

  • test-e2e-sandbox (medium): Useful adjacent confidence for the rebuilt production/test sandbox image after sandbox-init.sh changed, though gateway isolation is the targeted security-boundary check.
  • cloud-e2e (high): Optional sanity check for the normal OpenClaw install/onboard/live inference path without the security-posture residual-cap opt-in, confirming the new env forwarding does not affect standard users.
  • hermes-e2e (high): Optional sanity check for the normal Hermes install/onboard/live inference path without security-posture flags, since test-hermes-e2e.sh was touched but the changed branch is only active for security-posture runs.

New E2E recommendations

  • None.

Dispatch hint

  • Workflow: .github/workflows/nightly-e2e.yaml
  • jobs input: openclaw-onboard-security-posture-e2e,hermes-onboard-security-posture-e2e

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. No scenario workflow, scenario metadata, scenario runtime, or validation-suite files changed.

Optional scenario E2E

  • None.

Relevant changed files

  • None.

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 0 needs attention, 3 worth checking, 0 nice ideas
Since last review: 1 prior item resolved, 2 still apply, 0 new items found

Review findings

🛠️ Needs attention

  • None.

🔎 Worth checking

  • Source-of-truth review needed: Residual capability fallback and `NEMOCLAW_ALLOW_RESIDUAL_CAPS` compatibility escape hatch: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `scripts/lib/sandbox-init.sh:290` documents the Brev shadecloud opt-in and `docs/reference/commands.mdx:1264` documents the env var, but neither defines a retirement condition.
  • Security-posture E2Es opt into weakened residual-cap mode (.github/workflows/nightly-e2e.yaml:684): The two full onboard jobs named `openclaw-onboard-security-posture-e2e` and `hermes-onboard-security-posture-e2e` now set `NEMOCLAW_ALLOW_RESIDUAL_CAPS=1`, and the corresponding E2E scripts also default that opt-in when the security-posture/non-root flags are set. That is an explicit operator bypass for the new fail-closed capability policy, so these jobs can pass while running in the weaker posture they appear to be validating.
    • Recommendation: Keep compatibility coverage for affected non-root hosts, but split or rename it so the weaker posture is explicit, and add or identify a full onboard/runtime security-posture validation that runs without `NEMOCLAW_ALLOW_RESIDUAL_CAPS` and proves either successful capability dropping or the new refusal path.
    • Evidence: Workflow `env_json` adds `NEMOCLAW_ALLOW_RESIDUAL_CAPS":"1"` for both security-posture jobs at `.github/workflows/nightly-e2e.yaml:684` and `:702`; `test/e2e/test-full-e2e.sh:142` and `test/e2e/test-hermes-e2e.sh:189` export the same default under `NEMOCLAW_E2E_SECURITY_POSTURE=1` and `NEMOCLAW_E2E_EXPECT_NON_ROOT_HOST=1`.
  • Document the removal condition for the residual-cap escape hatch (scripts/lib/sandbox-init.sh:290): `NEMOCLAW_ALLOW_RESIDUAL_CAPS=1` is a localized compatibility escape hatch for hosts where the runtime cannot grant `CAP_SETPCAP` or where `capsh` is unavailable. The patch identifies the invalid state, source boundary, and regression tests, but it still does not state when this weaker-posture escape hatch should be deprecated or removed.
    • Recommendation: Add a short comment or docs note with the retirement condition, for example: remove or deprecate `NEMOCLAW_ALLOW_RESIDUAL_CAPS` once OpenShell/Brev/container runtime provisioning guarantees either `CAP_SETPCAP` for the entrypoint or pre-dropped bounding sets for NemoClaw sandboxes.
    • Evidence: `scripts/lib/sandbox-init.sh:290` documents the opt-in for environments like Brev shadecloud, and `docs/reference/commands.mdx:1264` documents the env var and weaker posture, but neither changed surface defines a removal/deprecation condition.

🌱 Nice ideas

  • None.
Since last review details

Current findings:

  • Source-of-truth review needed: Residual capability fallback and `NEMOCLAW_ALLOW_RESIDUAL_CAPS` compatibility escape hatch: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `scripts/lib/sandbox-init.sh:290` documents the Brev shadecloud opt-in and `docs/reference/commands.mdx:1264` documents the env var, but neither defines a retirement condition.
  • Security-posture E2Es opt into weakened residual-cap mode (.github/workflows/nightly-e2e.yaml:684): The two full onboard jobs named `openclaw-onboard-security-posture-e2e` and `hermes-onboard-security-posture-e2e` now set `NEMOCLAW_ALLOW_RESIDUAL_CAPS=1`, and the corresponding E2E scripts also default that opt-in when the security-posture/non-root flags are set. That is an explicit operator bypass for the new fail-closed capability policy, so these jobs can pass while running in the weaker posture they appear to be validating.
    • Recommendation: Keep compatibility coverage for affected non-root hosts, but split or rename it so the weaker posture is explicit, and add or identify a full onboard/runtime security-posture validation that runs without `NEMOCLAW_ALLOW_RESIDUAL_CAPS` and proves either successful capability dropping or the new refusal path.
    • Evidence: Workflow `env_json` adds `NEMOCLAW_ALLOW_RESIDUAL_CAPS":"1"` for both security-posture jobs at `.github/workflows/nightly-e2e.yaml:684` and `:702`; `test/e2e/test-full-e2e.sh:142` and `test/e2e/test-hermes-e2e.sh:189` export the same default under `NEMOCLAW_E2E_SECURITY_POSTURE=1` and `NEMOCLAW_E2E_EXPECT_NON_ROOT_HOST=1`.
  • Document the removal condition for the residual-cap escape hatch (scripts/lib/sandbox-init.sh:290): `NEMOCLAW_ALLOW_RESIDUAL_CAPS=1` is a localized compatibility escape hatch for hosts where the runtime cannot grant `CAP_SETPCAP` or where `capsh` is unavailable. The patch identifies the invalid state, source boundary, and regression tests, but it still does not state when this weaker-posture escape hatch should be deprecated or removed.
    • Recommendation: Add a short comment or docs note with the retirement condition, for example: remove or deprecate `NEMOCLAW_ALLOW_RESIDUAL_CAPS` once OpenShell/Brev/container runtime provisioning guarantees either `CAP_SETPCAP` for the entrypoint or pre-dropped bounding sets for NemoClaw sandboxes.
    • Evidence: `scripts/lib/sandbox-init.sh:290` documents the opt-in for environments like Brev shadecloud, and `docs/reference/commands.mdx:1264` documents the env var and weaker posture, but neither changed surface defines a removal/deprecation condition.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 26474580027
Target ref: c282694214ae2696f5b2df2000430627ff50d6f7
Workflow ref: main
Requested jobs: openclaw-onboard-security-posture-e2e
Summary: 0 passed, 1 failed, 0 skipped

Job Result
openclaw-onboard-security-posture-e2e ❌ failure

Failed jobs: openclaw-onboard-security-posture-e2e. Check run artifacts for logs.

@cjagwani cjagwani self-assigned this May 26, 2026
@cjagwani cjagwani added v0.0.52 integration: hermes Hermes integration behavior and removed v0.0.50 labels May 26, 2026
@cv cv added v0.0.53 and removed v0.0.52 labels May 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 3756-3761: The added env-arg injection for
NEMOCLAW_ALLOW_RESIDUAL_CAPS is causing top-level growth in src/lib/onboard.ts;
extract that logic into a helper inside src/lib/onboard/ (e.g., create a new
function like buildEntrypointEnvArgs or add to an existing helper such as
getOnboardEnvArgs) that returns the formatted env assignment using
formatEnvAssignment("NEMOCLAW_ALLOW_RESIDUAL_CAPS","1") when
process.env.NEMOCLAW_ALLOW_RESIDUAL_CAPS === "1", then replace the inline
envArgs.push(...) in onboard.ts with a single call to that helper (keeping the
same use of envArgs and formatEnvAssignment) so the file’s net line-count
doesn’t grow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: de929403-1e6b-493c-9c83-1ac760299253

📥 Commits

Reviewing files that changed from the base of the PR and between c282694 and 7cb6be6.

📒 Files selected for processing (8)
  • .github/workflows/nightly-e2e.yaml
  • docs/reference/commands.mdx
  • scripts/lib/sandbox-init.sh
  • src/lib/onboard.ts
  • test/e2e-gateway-isolation.sh
  • test/e2e/test-full-e2e.sh
  • test/e2e/test-hermes-e2e.sh
  • test/sandbox-init.test.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/reference/commands.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/lib/sandbox-init.sh

Comment thread src/lib/onboard.ts
Comment on lines +3756 to +3761
if (process.env.NEMOCLAW_ALLOW_RESIDUAL_CAPS === "1") {
// Runtime-only operator acknowledgement for hosts that cannot grant
// CAP_SETPCAP (for example Brev shadecloud). Do not bake this into image
// layers; pass it only to the sandbox entrypoint invocation.
envArgs.push(formatEnvAssignment("NEMOCLAW_ALLOW_RESIDUAL_CAPS", "1"));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

CI budget blocker: move this onboarding-entrypoint growth out of src/lib/onboard.ts.

The logic is good, but this addition is currently blocking merge: CI reports top-level onboard entrypoint growth (+6 lines). Since the budget only allows growth in src/lib/onboard/ modules, please relocate this env-arg injection behind an existing/new helper in an src/lib/onboard/* module (or otherwise keep net-zero growth in this file).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/onboard.ts` around lines 3756 - 3761, The added env-arg injection for
NEMOCLAW_ALLOW_RESIDUAL_CAPS is causing top-level growth in src/lib/onboard.ts;
extract that logic into a helper inside src/lib/onboard/ (e.g., create a new
function like buildEntrypointEnvArgs or add to an existing helper such as
getOnboardEnvArgs) that returns the formatted env assignment using
formatEnvAssignment("NEMOCLAW_ALLOW_RESIDUAL_CAPS","1") when
process.env.NEMOCLAW_ALLOW_RESIDUAL_CAPS === "1", then replace the inline
envArgs.push(...) in onboard.ts with a single call to that helper (keeping the
same use of envArgs and formatEnvAssignment) so the file’s net line-count
doesn’t grow.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26520084452
Target ref: 7cb6be6c47d917bc4e41b234592f16d8b23afe97
Workflow ref: main
Requested jobs: openclaw-onboard-security-posture-e2e,hermes-onboard-security-posture-e2e
Summary: 2 passed, 0 failed, 0 skipped

Job Result
hermes-onboard-security-posture-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success

@cv

cv commented May 27, 2026

Copy link
Copy Markdown
Collaborator

Updated this PR to address the advisor feedback:

  • handled report_residual_capabilities under set -e so the refusal banner and NEMOCLAW_ALLOW_RESIDUAL_CAPS=1 path always run
  • added unit coverage for the CAP_SETPCAP-unavailable + dangerous CapBnd branch, including opt-in continuation
  • added gateway-isolation E2E coverage for default fail-closed behavior plus explicit opt-in continuation
  • propagated/documented NEMOCLAW_ALLOW_RESIDUAL_CAPS=1 for onboard/security-posture E2Es

Local/push-hook checks passed: npx vitest run test/sandbox-init.test.ts, npm run typecheck:cli -- --pretty false, env-var docs gate, bash syntax, pre-push hooks.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26520612478
Target ref: d53ebcdd092040454633f4fe8049f1e6b3ecdd54
Workflow ref: main
Requested jobs: openclaw-onboard-security-posture-e2e,hermes-onboard-security-posture-e2e
Summary: 2 passed, 0 failed, 0 skipped

Job Result
hermes-onboard-security-posture-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success

@cv
cv merged commit 8682ee6 into main May 27, 2026
31 checks passed
cv added a commit that referenced this pull request May 27, 2026
## Summary
Reverts the residual-capability fail-closed behavior from #4266 and the
CI residual-cap opt-in from #4335. This restores the prior behavior
where sandbox entrypoints warn about residual dangerous capabilities
instead of refusing to start when CAP_SETPCAP is unavailable.

## Related Issue
Reverts #4266.
Reverts #4335.

## Changes
- Removed the `NEMOCLAW_ALLOW_RESIDUAL_CAPS` entrypoint opt-in and
fail-closed residual-capability policy from
`scripts/lib/sandbox-init.sh` and `src/lib/onboard.ts`.
- Removed the workflow-level residual-capability opt-in from reusable
and nightly E2E workflows.
- Reverted the related E2E, sandbox-init, workflow-contract, and
command-reference test/doc updates.

## Type of Change
- [ ] Code change (feature, bug fix, or refactor)
- [x] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Verification
- [x] `npx prek run --all-files` passes
- [x] `npm test` passes
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [x] Docs updated for user-facing behavior changes
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
Signed-off-by: Carlos Villela <cvillela@nvidia.com>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Removed residual-capabilities allowlist from CI workflows and sandbox
startup; sandbox now forwards runtime tool tokens and explicitly strips
host kube/SSH credentials.
  * Streamlined environment-variable handling for sandbox operations.

* **Bug Fixes**
* Improved capability-drop failure handling and residual-capability
reporting to avoid forced failures.

* **Tests**
* Simplified non-root execution checks and updated workflow contract
types and e2e test flows.

* **Documentation**
  * Removed deprecated onboarding configuration entry.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/NemoClaw/pull/4341?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 3, 2026
cv pushed a commit that referenced this pull request Jun 3, 2026
## Summary
On hosts without CAP_SETPCAP (GitHub runners, Brev shadecloud, Colossus
Ubuntu
24.04, Docker Desktop, WSL), `drop_capabilities` cannot run `capsh
--drop`, so
dangerous bounding-set caps survive and the agent boots with a weaker
posture
than the security model assumes. This adds an opt-in fail-closed guard
(`NEMOCLAW_REQUIRE_CAP_DROP=1`) that verifies the agent process tree's
actual
bounding set and refuses to start if dangerous capabilities remain.

## Related Issue
Refs #3280

<!-- Refs (not Closes): this hardens the agent process tree only. The
`nemoclaw connect` shell inherits the container's OCI bounding set and
is not
affected; tightening that needs cap_drop at sandbox-create, tracked
upstream in
NVIDIA/OpenShell#1452. #3280 should stay open pending that. -->

## Changes
- `scripts/lib/sandbox-init.sh`:
  - `enforce_cap_drop_if_required` runs on **every** path out of
`drop_capabilities` and verifies the **actual** `CapBnd` rather than
trusting
    the `NEMOCLAW_CAPS_DROPPED` sentinel (closes a strict-mode bypass).
- A single `DANGEROUS_CAPS` list feeds both the `capsh --drop` arguments
and
the verifier, so the drop-set and the verify-set (all 10 caps) cannot
drift.
- A non-empty but unparseable `CapBnd` is treated as unverifiable:
refuse in
strict mode, warn in default mode — never a raw bash arithmetic error.
- `setpriv`-based privilege step-down strips the remaining load-bearing
caps
    atomically with the setuid transition (falls back to `gosu` when
    `setpriv`/`CAP_SETPCAP` are unavailable).
- Default stays **warn-and-continue** (zero regression — the inverse of
the
reverted #4266); operators set `NEMOCLAW_REQUIRE_CAP_DROP=1` to
refuse-to-start.
- `test/sandbox-init.test.ts`: repro + strict-mode + sentinel-bypass +
  malformed-`CapBnd` coverage, seam-driven (`NEMOCLAW_PROC_STATUS`) and
  deterministic.
- `docs/security/best-practices.mdx`,
`docs/deployment/sandbox-hardening.mdx`:
  document `NEMOCLAW_REQUIRE_CAP_DROP` and the verified scope.

## Type of Change
- [ ] Code change (feature, bug fix, or refactor)
- [x] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Verification
- [x] `npx prek run --all-files` passes
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [x] Docs updated for user-facing behavior changes

<!-- test/sandbox-init.test.ts 37/37 (vitest). pre-commit + pre-push
hooks
(shellcheck, shfmt, TypeScript CLI, Test CLI, commitlint, DCO, gitleaks)
pass on
each push; full PR CI green incl. test-e2e-sandbox /
test-non-root-sandbox-smoke. -->

---
Signed-off-by: Dongni Yang <dongniy@nvidia.com>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Opt-in strict verification via NEMOCLAW_REQUIRE_CAP_DROP=1: agent can
refuse to start if dangerous Linux capabilities remain.

* **Behavior**
* More accurate detection and clearer diagnostics of residual
bounding-set capabilities; improved sandbox step-down argument handling.

* **Tests**
* Added deterministic tests covering warn-and-continue, strict-mode
refusal, and various verification edge cases.

* **Documentation**
* Updated docs explaining capability-drop behavior and the strict
verification option.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wscurran wscurran removed the bug label Jun 8, 2026
@cv
cv deleted the fix/4264-cap-setpcap-loud-warn branch June 28, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression integration: hermes Hermes integration behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Brev shadecloud][Sandbox] CAP_SETPCAP unavailable — nemoclaw-start can't drop bounding caps; security posture silently weaker than claimed

3 participants