Skip to content

fix(e2e): enforce split process security posture - #8633

Merged
cv merged 2 commits into
mainfrom
codex/enforce-split-process-posture
Aug 9, 2026
Merged

fix(e2e): enforce split process security posture#8633
cv merged 2 commits into
mainfrom
codex/enforce-split-process-posture

Conversation

@apurvvkumaria

@apurvvkumaria apurvvkumaria commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Correct the trusted security-posture E2E assertion to verify OpenShell's split-process model instead of requiring PID 1 to be nonroot. PID 1 now passes only as the exact constrained OpenShell supervisor, while exactly one nonroot, capability-free nemoclaw-start child supervisor must be present.

Changes

  • Replace the retired per-agent nonroot PID 1 expectation with one required split-process contract for the OpenClaw and Hermes security-posture consumers.
  • Inspect the selected OpenShell container through NemoClaw's sanitized privileged-exec boundary, an expected full container ID, and /usr/bin/python3 -I.
  • Bind Docker discovery and privileged probing to the same frozen resolver environment and runtime endpoint; reject selector, endpoint, or environment drift before inspection.
  • Fail closed on supervisor command, identity, supplementary-group, capability, or NoNewPrivs drift and on any missing, ambiguous, privileged, stopped, or malformed nemoclaw-start child supervisor.
  • Protect the workflow producer and consumer contract with mutation tests and the exact CLI artifact fingerprint.
  • Keep this repair scoped to the shared final-convergence assertion. It does not claim direct live /proc observations at every intermediate lifecycle instant or immediately after rebuild and rollback; those remain path-owned E2E coverage residuals.

The host-side process probe is required because an ordinary sandbox-side command is itself a child process and cannot independently attest the PID 1 boundary. security-posture.test.ts, security-posture-workflow-boundary.test.ts, and cli-artifact-workflow-boundary.test.ts protect that contract.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: This changes only an internal E2E assertion and workflow contract. It does not change commands, configuration, defaults, policy schemas, or supported runtime behavior.
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Independent nine-category security and correctness reviews passed for ce36aadc0; no waiver is used.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: no-docs-needed
  • Evidence: This PR changes only internal E2E security-posture assertions, workflow contracts, and runtime-endpoint binding. It does not change user-facing commands, configuration, defaults, policy schemas, or supported runtime behavior. Existing process-control and command-reference pages already describe OpenShell as PID 1 with exactly one nonroot nemoclaw-start supervisor.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result:
  • Supporting evidence:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — frozen-head evidence for ce36aadc0: four affected E2E-support contract suites, 96 passed; adjacent privileged-exec, subprocess-environment, portable-lifecycle, and socket-authority suites, 109 passed; OpenShell migration review, 4 passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — Not rerun on ce36aadc0; the focused frozen-head suites above and all path-scoped hooks passed. Authoritative live validation is the post-merge trusted-main security-posture run.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Apurv Kumaria akumaria@nvidia.com

Summary by CodeRabbit

  • Security Improvements

    • Updated security posture checks to verify OpenShell’s split-process architecture, including supervisor and child-process identities, privileges, and container isolation.
    • Removed reliance on the legacy non-root entrypoint expectation.
  • Bug Fixes

    • Improved validation and reporting for process security configuration.
    • Added fail-fast checks when required split-process security settings are missing or inconsistent.
  • Tests

    • Expanded end-to-end coverage for process isolation, security properties, workflow configuration, and CLI artifact integrity.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@apurvvkumaria apurvvkumaria self-assigned this Aug 8, 2026
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: 360effdc-3c57-4c09-a3cc-55c13857500e

📥 Commits

Reviewing files that changed from the base of the PR and between a8488a0 and ce36aad.

📒 Files selected for processing (2)
  • test/e2e/fixtures/security-posture.ts
  • test/e2e/support/security-posture.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/e2e/support/security-posture.test.ts

📝 Walkthrough

Walkthrough

The E2E security posture checks now validate OpenShell’s split-process architecture. They inspect supervisor and child-supervisor identities through a privileged /proc probe, update workflow contracts, and remove legacy non-root entrypoint checks.

Changes

OpenShell split-process posture

Layer / File(s) Summary
Workflow split-process contract
.github/workflows/e2e.yaml, tools/e2e/*workflow-boundary.mts, test/e2e/support/security-posture-workflow-boundary.test.ts
The workflow requires NEMOCLAW_E2E_EXPECT_OPENSHELL_SPLIT_PROCESS=1 and rejects the retired entrypoint flag. The CLI artifact contract hash is updated.
Process probe and report validation
test/e2e/fixtures/security-posture.ts
A bounded Python probe reports process identities. Type and runtime validation checks supervisor and child-supervisor IDs, commands, capabilities, executable paths, groups, and NoNewPrivs.
Posture assertion integration
test/e2e/fixtures/security-posture.ts
assertSecurityPosture discovers the OpenShell container, validates container identity and runtime endpoint state, runs the privileged probe, and returns both supervisor identities.
Split-process validation coverage
test/e2e/support/security-posture.test.ts
Tests cover probe isolation, environment handling, malformed reports, process mutations, container selection, runtime endpoints, command execution, summary output, and fail-fast behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SecurityPostureTest
  participant assertSecurityPosture
  participant Docker
  participant OpenShellContainer
  participant PythonProbe
  SecurityPostureTest->>assertSecurityPosture: Request split-process posture
  assertSecurityPosture->>Docker: Find matching OpenShell container
  Docker->>OpenShellContainer: Run privileged security probe
  OpenShellContainer->>PythonProbe: Inspect bounded /proc data
  PythonProbe-->>assertSecurityPosture: Return validated JSON report
  assertSecurityPosture-->>SecurityPostureTest: Return supervisor identities
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#8583: Covers related OpenShell supervisor, process identity, capability, argument, and container validation.

Suggested labels: area: security, bug-fix

Suggested reviewers: cv, senthilr-nv

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 The title clearly and concisely describes the main change: enforcing the OpenShell split-process security posture in E2E tests.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/enforce-split-process-posture

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

@github-code-quality

github-code-quality Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit ce36aad in the codex/enforce-split-... branch remains at 96%, unchanged from commit 87f27ae in the main branch.


Updated August 08, 2026 23:00 UTC

@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: 2

🧹 Nitpick comments (1)
test/e2e/fixtures/security-posture.ts (1)

354-362: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the probe literals from the shared TypeScript constants.

The accepted nemoclaw-start argv forms and the bash executable list exist twice. The Python probe declares them at lines 93-95. This function and SYSTEM_BASH_EXECUTABLES at line 73 declare them again. If one list changes, the census and the validator disagree, and the failure message points at the wrong cause. The probe template already interpolates MAX_PROC_ENTRIES at line 90, so the same approach works here.

♻️ Proposed refactor sketch

Declare the accepted values once near the other constants:

const NEMOCLAW_START_SUPERVISOR_PATHS = ["nemoclaw-start", "/usr/local/bin/nemoclaw-start"] as const;
const BASH_ARGV0 = ["bash", "/bin/bash", "/usr/bin/bash"] as const;

Then interpolate them into the probe and reuse them here:

 function canonicalNemoclawStartSupervisorArgv(argv: string[]): boolean {
-  const starts = ["nemoclaw-start", "/usr/local/bin/nemoclaw-start"];
+  const starts = NEMOCLAW_START_SUPERVISOR_PATHS as readonly string[];
   if (argv.length === 1 && starts.includes(argv[0] ?? "")) return true;
   return (
     argv.length === 2 &&
-    ["bash", "/bin/bash", "/usr/bin/bash"].includes(argv[0] ?? "") &&
+    (BASH_ARGV0 as readonly string[]).includes(argv[0] ?? "") &&
     starts.includes(argv[1] ?? "")
   );
 }
🤖 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 `@test/e2e/fixtures/security-posture.ts` around lines 354 - 362, Define shared
TypeScript constants for the accepted nemoclaw-start paths and bash executable
values near the existing constants, then interpolate those constants into the
Python probe template and reuse them in canonicalNemoclawStartSupervisorArgv and
SYSTEM_BASH_EXECUTABLES. Remove the duplicated literal lists so census and
validation always use the same values.
🤖 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 `@test/e2e/fixtures/security-posture.ts`:
- Around line 554-573: Update the container discovery command in the
security-posture flow to use the same resolved endpoint as privileged probing,
derived from dockerHost (or validate endpoint equality before discovery).
Preserve the existing managed-by and sandbox-name filters, formatting, and
parseOpenShellContainerId behavior while ensuring docker ps targets the selected
container runtime socket.

In `@test/e2e/support/security-posture.test.ts`:
- Around line 108-141: Update both spawnSync checks in the Python compilation
and isolation tests to assert that the returned result has no error before
checking status, using the respective compiled.error and isolated.error values
so a missing python3 interpreter is reported clearly. Preserve the existing
status and stdout assertions after these guards.

---

Nitpick comments:
In `@test/e2e/fixtures/security-posture.ts`:
- Around line 354-362: Define shared TypeScript constants for the accepted
nemoclaw-start paths and bash executable values near the existing constants,
then interpolate those constants into the Python probe template and reuse them
in canonicalNemoclawStartSupervisorArgv and SYSTEM_BASH_EXECUTABLES. Remove the
duplicated literal lists so census and validation always use the same values.
🪄 Autofix

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: 23288b73-97d6-4346-9b1b-e98ca5cf4f5a

📥 Commits

Reviewing files that changed from the base of the PR and between 87f27ae and a8488a0.

📒 Files selected for processing (6)
  • .github/workflows/e2e.yaml
  • test/e2e/fixtures/security-posture.ts
  • test/e2e/support/security-posture-workflow-boundary.test.ts
  • test/e2e/support/security-posture.test.ts
  • tools/e2e/cli-artifact-workflow-boundary.mts
  • tools/e2e/security-posture-workflow-boundary.mts

Comment thread test/e2e/fixtures/security-posture.ts
Comment thread test/e2e/support/security-posture.test.ts
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Failed after a partial review · low confidence · 0 blockers · 0 warnings · 0 suggestions

Second-opinion terminology and E2E selections are advisory. Live E2E does not run automatically for pull requests.

3 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • justified — child supervisor at test/e2e/fixtures/security-posture.ts:432: Use child supervisor where the direct non-root nemoclaw-start process must be distinguished from the OpenShell supervisor.
  • define — split-process security report at test/e2e/fixtures/security-posture.ts:459: Define this term near its first explanatory use if it becomes a shared repository concept.
  • justified — privileged Docker environment at test/e2e/fixtures/security-posture.ts:264: Use privileged Docker environment only for the sanitized environment used by privileged Docker inspection.

E2E guidance

Advisory only. A maintainer can dispatch the default E2E suite against this exact revision.

Recommended E2E: cloud-inference, cloud-onboard, security-posture

2 optional E2E recommendations
  • rebuild-openclaw
  • rebuild-hermes

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@cv
cv merged commit c3bbad7 into main Aug 9, 2026
79 of 85 checks passed
@cv
cv deleted the codex/enforce-split-process-posture branch August 9, 2026 00:58
@github-actions github-actions Bot added the v0.0.106 Release target label Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v0.0.106 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants