Skip to content

fix(sandbox): ensure procps survives hardening and stale base images (#2343)#2408

Merged
jyaunches merged 2 commits into
mainfrom
fix/2343-sandbox-procps-robust
Apr 24, 2026
Merged

fix(sandbox): ensure procps survives hardening and stale base images (#2343)#2408
jyaunches merged 2 commits into
mainfrom
fix/2343-sandbox-procps-robust

Conversation

@ericksoa

@ericksoa ericksoa commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #2356. The adversarial PR review found that procps tools (ps, top, free, uptime, vmstat) were still missing inside a real sandbox runtime even after #2356 added procps to Dockerfile.base. Root cause: the GHCR base image may not have been rebuilt yet, and the Dockerfile hardening step (apt-get autoremove --purge) could strip it.

This PR adds a three-layer defense in the production Dockerfile:

  • apt-mark manual procps before the autoremove step, so apt never considers it auto-removable
  • Conditional apt-get install procps if ps is still missing after hardening (handles stale GHCR base images that predate feat(sandbox): add procps for ps/top/kill debug tools (#2343) #2356)
  • Build-time ps --version smoke test that fails the Docker build if procps didn't make it through

Plus regression tests:

  • Static guards in sandbox-provisioning.test.ts verifying both Dockerfiles contain procps provisions
  • Runtime E2E test in e2e-test.sh verifying all five procps tools are executable inside the sandbox container

Test plan

  • hadolint Dockerfile passes
  • hadolint Dockerfile.base passes
  • vitest run test/sandbox-provisioning.test.ts passes
  • CI test-e2e-sandbox job passes (runs e2e-test.sh inside container, including new test 11)
  • Docker build succeeds with both fresh base image and stale GHCR base

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added end-to-end checks that verify common system debug tools (ps, top, free, uptime, vmstat) run in the sandbox.
    • Added regression tests ensuring Docker provisioning includes the debug tooling.
  • Chores

    • Improved Docker provisioning to ensure procps/debug tools are present at runtime, with a fallback install path for older base images.

…2343)

Follow-up to #2356. The base image addition alone does not guarantee
procps is present in the production image — the GHCR base may not have
been rebuilt yet, and apt-get autoremove in the hardening step could
strip it. Add apt-mark manual + conditional install fallback in the
production Dockerfile with a build-time smoke test, plus static and
runtime regression tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 24, 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: 07ae3a62-9cec-4635-873b-7cff36288d92

📥 Commits

Reviewing files that changed from the base of the PR and between c140feb and aaf39c6.

📒 Files selected for processing (1)
  • Dockerfile

📝 Walkthrough

Walkthrough

Adds procps provisioning to images: Dockerfile.base installs a pinned procps; Dockerfile preserves/conditionally reinstalls procps during hardening and verifies ps at runtime; tests and E2E steps validate presence and executability of procps utilities.

Changes

Cohort / File(s) Summary
Docker Runtime Hardening
Dockerfile
Marks procps as manually installed before purge/autoremove, conditionally installs a pinned procps if ps is absent, removes apt lists, and emits ps --version to verify tooling.
Base Image Configuration
Dockerfile.base
Adds a pinned procps package to the base image apt-get install list so procps utilities are present in the base layer.
E2E Testing
test/e2e-test.sh
Adds E2E step verifying presence of ps, top, free, uptime, vmstat in $PATH and ensures ps --version executes successfully.
Provisioning Validation Tests
test/sandbox-provisioning.test.ts
Adds static tests asserting Dockerfile.base installs procps and Dockerfile contains command -v ps check plus fallback install logic for older base images.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I nibbled code and found a fix,

ps, top, free — no missing tricks.
From base to runtime, snug and spry,
Debug tools hop, and tests comply. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and specifically identifies the main change: ensuring procps robustness in the sandbox Docker image by addressing both the hardening step and stale base image scenarios.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/2343-sandbox-procps-robust

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

@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

🧹 Nitpick comments (1)
test/sandbox-provisioning.test.ts (1)

63-72: Tighten regex guards to reduce false positives in static checks.

Line 64 and Line 71 patterns are broad and can still pass after unintended Dockerfile edits. Consider matching the exact hardening invariants (apt-mark manual procps, fallback install, and ps --version smoke check).

Suggested test tightening
 it("Dockerfile.base installs procps in the apt-get layer", () => {
-  expect(baseSrc).toMatch(/apt-get.*install.*procps/s);
+  expect(baseSrc).toMatch(/apt-get\s+update\s*&&\s*apt-get\s+install[\s\S]*\bprocps=2:4\.0\.2-3\b/);
 });

 it("Dockerfile has a procps fallback for stale GHCR base images", () => {
   // The hardening step must protect procps from autoremove and install it
   // if the base image predates the procps addition.
+  expect(mainSrc).toMatch(/apt-mark\s+manual\s+procps/);
   expect(mainSrc).toMatch(/command -v ps/);
-  expect(mainSrc).toMatch(/install.*procps/);
+  expect(mainSrc).toMatch(/apt-get\s+install\s+-y\s+--no-install-recommends\s+procps=2:4\.0\.2-3/);
+  expect(mainSrc).toMatch(/ps --version/);
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/sandbox-provisioning.test.ts` around lines 63 - 72, The tests use broad
regexes that yield false positives; tighten the assertions in the
"Dockerfile.base installs procps in the apt-get layer" and "Dockerfile has a
procps fallback for stale GHCR base images" tests to match the exact hardening
invariants: assert baseSrc contains the apt-mark invocation (e.g., match
/apt-mark\s+manual\s+procps/), assert mainSrc contains the explicit ps smoke
check (e.g., /ps\s+--version/ or /command\s+-v\s+ps/ depending on the script)
and the fallback install of procps (e.g., /\bapt-get\b.*\binstall\b.*\bprocps\b/
or the exact flags you use like
/apt-get\s+install.*--no-install-recommends.*procps/); update the expect calls
that reference baseSrc and mainSrc accordingly so they verify these precise
invariants.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/e2e-test.sh`:
- Around line 419-431: The script currently only smoke-tests execution for ps;
update the existence loop (the for loop iterating over cmd and using pass/fail)
to also attempt a safe, non-interactive execution of each found tool (using a
tried sequence such as --version, -V, or --help alternatives until one succeeds)
and call pass "<cmd> executes successfully" or fail "<cmd> found but failed to
execute" via the same pass/fail helpers; locate the loop that declares cmd and
the subsequent ps-only check and replace the separate ps execution check with
per-cmd execution attempts that use the cmd variable and reuse the pass/fail
functions (ensuring no interactive flags are used).

---

Nitpick comments:
In `@test/sandbox-provisioning.test.ts`:
- Around line 63-72: The tests use broad regexes that yield false positives;
tighten the assertions in the "Dockerfile.base installs procps in the apt-get
layer" and "Dockerfile has a procps fallback for stale GHCR base images" tests
to match the exact hardening invariants: assert baseSrc contains the apt-mark
invocation (e.g., match /apt-mark\s+manual\s+procps/), assert mainSrc contains
the explicit ps smoke check (e.g., /ps\s+--version/ or /command\s+-v\s+ps/
depending on the script) and the fallback install of procps (e.g.,
/\bapt-get\b.*\binstall\b.*\bprocps\b/ or the exact flags you use like
/apt-get\s+install.*--no-install-recommends.*procps/); update the expect calls
that reference baseSrc and mainSrc accordingly so they verify these precise
invariants.
🪄 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: 8d37a51f-caad-4522-b257-83988f21c48f

📥 Commits

Reviewing files that changed from the base of the PR and between 4202bdb and c140feb.

📒 Files selected for processing (4)
  • Dockerfile
  • Dockerfile.base
  • test/e2e-test.sh
  • test/sandbox-provisioning.test.ts

Comment thread test/e2e-test.sh
Comment on lines +419 to +431
for cmd in ps top free uptime vmstat; do
if command -v "$cmd" >/dev/null 2>&1; then
pass "$cmd is available at $(command -v "$cmd")"
else
fail "$cmd not found — procps package missing from sandbox image"
fi
done
# Smoke-test: ps must actually execute, not just resolve
if ps --version >/dev/null 2>&1; then
pass "ps executes successfully"
else
fail "ps found but failed to execute"
fi

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 | 🟡 Minor

Validate execution for all five tools, not only ps.

Line 419 currently proves PATH presence, but Lines 427-431 only smoke-test ps. To match the stated runtime guarantee, execute each tool with a safe non-interactive invocation.

Proposed hardening diff
-for cmd in ps top free uptime vmstat; do
-  if command -v "$cmd" >/dev/null 2>&1; then
-    pass "$cmd is available at $(command -v "$cmd")"
-  else
-    fail "$cmd not found — procps package missing from sandbox image"
-  fi
-done
-# Smoke-test: ps must actually execute, not just resolve
-if ps --version >/dev/null 2>&1; then
-  pass "ps executes successfully"
-else
-  fail "ps found but failed to execute"
-fi
+for cmd in ps top free uptime vmstat; do
+  if ! command -v "$cmd" >/dev/null 2>&1; then
+    fail "$cmd not found — procps package missing from sandbox image"
+  fi
+  case "$cmd" in
+    ps) "$cmd" --version >/dev/null 2>&1 ;;
+    top) "$cmd" -b -n 1 >/dev/null 2>&1 ;;
+    free) "$cmd" -b >/dev/null 2>&1 ;;
+    uptime) "$cmd" >/dev/null 2>&1 ;;
+    vmstat) "$cmd" 1 1 >/dev/null 2>&1 ;;
+  esac || fail "$cmd found but failed to execute"
+  pass "$cmd is available and executable"
+done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for cmd in ps top free uptime vmstat; do
if command -v "$cmd" >/dev/null 2>&1; then
pass "$cmd is available at $(command -v "$cmd")"
else
fail "$cmd not found — procps package missing from sandbox image"
fi
done
# Smoke-test: ps must actually execute, not just resolve
if ps --version >/dev/null 2>&1; then
pass "ps executes successfully"
else
fail "ps found but failed to execute"
fi
for cmd in ps top free uptime vmstat; do
if ! command -v "$cmd" >/dev/null 2>&1; then
fail "$cmd not found — procps package missing from sandbox image"
fi
case "$cmd" in
ps) "$cmd" --version >/dev/null 2>&1 ;;
top) "$cmd" -b -n 1 >/dev/null 2>&1 ;;
free) "$cmd" -b >/dev/null 2>&1 ;;
uptime) "$cmd" >/dev/null 2>&1 ;;
vmstat) "$cmd" 1 1 >/dev/null 2>&1 ;;
esac || fail "$cmd found but failed to execute"
pass "$cmd is available and executable"
done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/e2e-test.sh` around lines 419 - 431, The script currently only
smoke-tests execution for ps; update the existence loop (the for loop iterating
over cmd and using pass/fail) to also attempt a safe, non-interactive execution
of each found tool (using a tried sequence such as --version, -V, or --help
alternatives until one succeeds) and call pass "<cmd> executes successfully" or
fail "<cmd> found but failed to execute" via the same pass/fail helpers; locate
the loop that declares cmd and the subsequent ps-only check and replace the
separate ps execution check with per-cmd execution attempts that use the cmd
variable and reuse the pass/fail functions (ensuring no interactive flags are
used).

@wscurran wscurran added bug Something fails against expected or documented behavior enhancement: testing dependencies Pull requests that update a dependency file labels Apr 24, 2026
@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this pull request that proposes a way to improve the compatibility of NemoClaw by ensuring procps survives hardening and stale base images. This identifies a bug that causes procps tools to be missing inside the sandbox runtime and proposes a three-layer defense to prevent it. The addition of regression tests and a build-time smoke test will help ensure the issue does not recur. Related open PRs: PR #2356. Related open issues: Issue #2343.


Related open PRs:


Related open issues:

@jyaunches jyaunches self-assigned this Apr 24, 2026
@jyaunches jyaunches self-requested a review April 24, 2026 17:54

@jyaunches jyaunches 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.

LGTM — clean procps hardening fix with three-layer defense (apt-mark manual, conditional install fallback, build-time smoke test). Tests are well-layered: static Dockerfile guards + E2E runtime verification. All CI green except wsl-e2e still running. Added hadolint DL3001 ignore for the intentional ps --version assertion.

@jyaunches jyaunches merged commit b804db0 into main Apr 24, 2026
18 checks passed
@cv cv added the v0.0.25 label Apr 24, 2026
DemianHeyGen pushed a commit to DemianHeyGen/NemoClaw that referenced this pull request Apr 30, 2026
…VIDIA#2343) (NVIDIA#2408)

## Summary

Follow-up to NVIDIA#2356. The adversarial PR review found that `procps` tools
(`ps`, `top`, `free`, `uptime`, `vmstat`) were still missing inside a
real sandbox runtime even after NVIDIA#2356 added `procps` to
`Dockerfile.base`. Root cause: the GHCR base image may not have been
rebuilt yet, and the `Dockerfile` hardening step (`apt-get autoremove
--purge`) could strip it.

This PR adds a three-layer defense in the production `Dockerfile`:
- **`apt-mark manual procps`** before the autoremove step, so apt never
considers it auto-removable
- **Conditional `apt-get install procps`** if `ps` is still missing
after hardening (handles stale GHCR base images that predate NVIDIA#2356)
- **Build-time `ps --version`** smoke test that fails the Docker build
if procps didn't make it through

Plus regression tests:
- Static guards in `sandbox-provisioning.test.ts` verifying both
Dockerfiles contain procps provisions
- Runtime E2E test in `e2e-test.sh` verifying all five procps tools are
executable inside the sandbox container

## Test plan

- [ ] `hadolint Dockerfile` passes
- [ ] `hadolint Dockerfile.base` passes
- [ ] `vitest run test/sandbox-provisioning.test.ts` passes
- [ ] CI `test-e2e-sandbox` job passes (runs `e2e-test.sh` inside
container, including new test 11)
- [ ] Docker build succeeds with both fresh base image and stale GHCR
base

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* **Tests**
* Added end-to-end checks that verify common system debug tools (ps,
top, free, uptime, vmstat) run in the sandbox.
* Added regression tests ensuring Docker provisioning includes the debug
tooling.

* **Chores**
* Improved Docker provisioning to ensure procps/debug tools are present
at runtime, with a fallback install path for older base images.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Julie Yaunches <jyaunches@nvidia.com>
ksapru pushed a commit to ksapru/NemoClaw that referenced this pull request May 12, 2026
…VIDIA#2343) (NVIDIA#2408)

## Summary

Follow-up to NVIDIA#2356. The adversarial PR review found that `procps` tools
(`ps`, `top`, `free`, `uptime`, `vmstat`) were still missing inside a
real sandbox runtime even after NVIDIA#2356 added `procps` to
`Dockerfile.base`. Root cause: the GHCR base image may not have been
rebuilt yet, and the `Dockerfile` hardening step (`apt-get autoremove
--purge`) could strip it.

This PR adds a three-layer defense in the production `Dockerfile`:
- **`apt-mark manual procps`** before the autoremove step, so apt never
considers it auto-removable
- **Conditional `apt-get install procps`** if `ps` is still missing
after hardening (handles stale GHCR base images that predate NVIDIA#2356)
- **Build-time `ps --version`** smoke test that fails the Docker build
if procps didn't make it through

Plus regression tests:
- Static guards in `sandbox-provisioning.test.ts` verifying both
Dockerfiles contain procps provisions
- Runtime E2E test in `e2e-test.sh` verifying all five procps tools are
executable inside the sandbox container

## Test plan

- [ ] `hadolint Dockerfile` passes
- [ ] `hadolint Dockerfile.base` passes
- [ ] `vitest run test/sandbox-provisioning.test.ts` passes
- [ ] CI `test-e2e-sandbox` job passes (runs `e2e-test.sh` inside
container, including new test 11)
- [ ] Docker build succeeds with both fresh base image and stale GHCR
base

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* **Tests**
* Added end-to-end checks that verify common system debug tools (ps,
top, free, uptime, vmstat) run in the sandbox.
* Added regression tests ensuring Docker provisioning includes the debug
tooling.

* **Chores**
* Improved Docker provisioning to ensure procps/debug tools are present
at runtime, with a fallback install path for older base images.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Julie Yaunches <jyaunches@nvidia.com>
@wscurran wscurran added area: e2e End-to-end tests, nightly failures, or validation infrastructure bug-fix PR fixes a bug or regression chore Build, CI, dependency, or tooling maintenance feature PR adds or expands user-visible functionality and removed enhancement: testing bug Something fails against expected or documented behavior chore Build, CI, dependency, or tooling maintenance feature PR adds or expands user-visible functionality labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: e2e End-to-end tests, nightly failures, or validation infrastructure bug-fix PR fixes a bug or regression dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants