Skip to content

fix(onboard): protect corporate CA bundle ownership - #8812

Merged
prekshivyas merged 7 commits into
mainfrom
fix/root-owned-corporate-ca-8803
Aug 12, 2026
Merged

fix(onboard): protect corporate CA bundle ownership#8812
prekshivyas merged 7 commits into
mainfrom
fix/root-owned-corporate-ca-8803

Conversation

@sandl99

@sandl99 sandl99 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

OpenClaw images that bake a corporate CA now select root startup, so the entrypoint creates the merged runtime trust bundle as root:root with mode 0444 before it starts sandbox-user commands.
Explicit corporate CA configuration now fails when a custom Dockerfile cannot prove that the runtime-user argument controls the final image user and that NemoClaw's trusted entrypoint performs the later privilege drop.

Related Issue

Fixes #8803

Changes

  • Pass the existing agent name into Dockerfile patching so the shared path changes only OpenClaw. The shared patch cannot infer its consumer, and the sibling-agent regression test protects Deep Agents Code startup behavior.
  • Select the existing OpenClaw root runtime user when NemoClaw bakes an explicit, conventional-variable, or host-anchor corporate CA.
  • Validate the final-stage OpenClaw runtime-user and trusted-entrypoint contract, fail explicit configuration when it is not met, and preserve the ambient-source no-op.
  • Accept case-insensitive Dockerfile instruction keywords while requiring the exact, case-sensitive runtime-user argument name.
  • Reject corporate CA baking before Dockerfile mutation when the staged agent identity is absent.
  • Require the live corporate CA probe to observe owner UID 0, group GID 0, and mode 0444 on the merged bundle.
  • Document the OpenClaw ownership boundary and custom Dockerfile contract in the corporate CA security guide.

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:
  • 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: security follow-up passed with no new blocker: fix(onboard): protect corporate CA bundle ownership #8812 (comment). Fresh hosted checks and required reviewer approval remain merge gates.
  • 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: docs-updated
  • Evidence: docs/security/configure-corporate-ca-trust.mdx; the follow-up review confirmed the omitted-agent guard is an internal fail-closed invariant and requires no additional documentation.
  • 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 — command/result or justification: corporate CA Dockerfile patch tests 14/14 on the current branch; corporate CA runtime integration tests 14/14; npm run test:changed -- --maxWorkers=50% 1,180/1,180; semantic E2E collection 125 tests across 81 files; npm run docs exited 0 with 0 errors and 2 Fern warnings.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • 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: San Dang sdang@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved corporate certificate authority handling for custom container configurations.
    • Ensured merged certificate bundles are readable by sandbox processes while protected from modification.
    • Added clearer validation and failure behavior for unsupported runtime users, entrypoints, or missing certificate settings.
    • Preserved fallback behavior across OpenClaw, Hermes, and Deep Agents Code configurations.
  • Tests

    • Expanded coverage for certificate injection, Dockerfile compatibility, fallback behavior, and bundle permissions.

@sandl99 sandl99 self-assigned this Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change updates corporate CA Dockerfile patching and onboarding wiring. OpenClaw CA builds select root for bundle creation, retain sandbox for commands, enforce required build arguments, and validate root ownership with mode 0444.

Changes

Corporate CA trust handling

Layer / File(s) Summary
Corporate CA patching and validation
src/lib/onboard/dockerfile-patch.ts, src/lib/onboard/dockerfile-patch-corporate-ca.test.ts
The patch helper accepts an agent name, validates the startup contract, selects root for OpenClaw CA builds, and covers explicit, fallback, no-CA, and invalid-contract cases.
Agent-name propagation through onboarding
src/lib/onboard/sandbox-dockerfile-patch-flow.ts, src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts
Onboarding passes managed agent names to Dockerfile patching for OpenClaw, Hermes, and LangChain Deep Agents Code.
Trust bundle contract and end-to-end verification
docs/security/configure-corporate-ca-trust.mdx, test/e2e/fixtures/corporate-ca.ts
Documentation describes variant-specific Dockerfile requirements. The end-to-end probe verifies root ownership and mode 0444 for the merged bundle.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Onboarding
  participant DockerfilePatch
  participant Dockerfile
  participant TrustedEntrypoint
  Onboarding->>DockerfilePatch: pass managed agent name
  DockerfilePatch->>Dockerfile: validate startup contract
  DockerfilePatch->>Dockerfile: select root for CA baking
  Dockerfile->>TrustedEntrypoint: start trusted entrypoint
  TrustedEntrypoint->>Dockerfile: create root-owned 0444 CA bundle
Loading

Possibly related PRs

Suggested labels: area: security, security, bug-fix

Suggested reviewers: cv

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #8803 by enforcing root:root ownership and mode 0444 while preserving bundle contents and TLS variable references.
Out of Scope Changes check ✅ Passed The Dockerfile logic, tests, probe, patch-flow updates, and documentation directly support issue #8803 and the stated PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: protecting ownership of the corporate CA bundle during onboarding.
✨ 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/root-owned-corporate-ca-8803

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

@github-code-quality

github-code-quality Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit f8f06f0 in the fix/root-owned-corpo... branch remains at 96%, unchanged from commit f4d811a in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit f8f06f0 in the fix/root-owned-corpo... branch remains at 82%, unchanged from commit de70924 in the main branch.


Updated August 11, 2026 20:57 UTC

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Aug 11, 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): Completed · high confidence · 0 blockers · 0 warnings · 2 suggestions
  • Model comparison: normalized findings differ; normalized terminology decisions differ; normalized E2E selections differ; Nemotron reported the same number of blockers, the same number of warnings, 2 more suggestions.
3 terminology differences from the second opinion

Advisory only. These are normalized differences from the primary terminology receipt.

  • merged bundle at test/e2e/fixtures/corporate-ca.ts:88: selected only by the second-opinion lane as established.
  • startup contract at docs/security/configure-corporate-ca-trust.mdx:106: selected only by the second-opinion lane as define.
  • staged Dockerfile agent identity at src/lib/onboard/dockerfile-patch.ts:554: selected only by the second-opinion lane as define.
3 additional E2E selections from the second opinion

Advisory only. The primary lane did not select these E2E jobs or targets.

  • rebuild-openclaw: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • openclaw-slack-pairing: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • openclaw-discord-pairing: The completed second-opinion lane identified E2E coverage that the primary lane omitted.

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.

  • established — root-owned at docs/security/configure-corporate-ca-trust.mdx:105: Use root-owned for the merged CA bundle ownership boundary.
  • define — runtime-user argument at src/lib/onboard/dockerfile-patch-corporate-ca.test.ts:208: Use the literal NEMOCLAW_MANAGED_IMAGE_RUNTIME_USER identifier when explaining this contract.
  • justified — trusted exec form at docs/security/configure-corporate-ca-trust.mdx:104: Retain trusted exec form with the literal required ENTRYPOINT instruction.

E2E guidance

Advisory only. A maintainer can dispatch the default E2E suite for the commit under review.

Recommended E2E: None

Manual-only E2E: cloud-inference, cloud-onboard, security-posture, onboard-repair, onboard-resume
The manual PR workflow does not run these selectors for the commit under review. Run them from reviewed code on main.

Workflow run details

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

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Maintainer security review: no blocking findings.

I reviewed the change across corporate CA input handling, Dockerfile argument validation, command and build-argument construction, filesystem ownership and symlink protections, root-to-sandbox privilege separation, secrets and logging, failure behavior, sibling-agent isolation, dependency impact, and documentation.

  • Root startup is selected only for OpenClaw when a validated corporate CA is actually baked. Hermes and Deep Agents keep their existing runtime-user behavior.
  • Explicit corporate CA configuration fails closed when an OpenClaw custom Dockerfile cannot satisfy both the CA and runtime-user contracts. Ambient sources remain a no-op for an incompatible custom Dockerfile.
  • The entrypoint creates the merged bundle before dispatch and later runs one-shot agent commands through the trusted setpriv sandbox transition. The live probe requires the bundle to be root:root with mode 0444.
  • Certificate contents are not logged, and the change does not alter certificate parsing, source validation, or dependency resolution.

Local evidence: 21 targeted onboarding tests and 14 runtime trust tests pass. CLI build and type-check, documentation validation, secret scanning, repository checks, and all pull-request-scoped hooks also pass. The OpenClaw and Deep Agents managed-image jobs passed; the first Hermes job built and exercised startup successfully before a registry publication token was denied, so that non-code failure was safely rerun.

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

CI follow-up:

  • The Hermes managed-image rerun passed, including image publication. Its first attempt had already passed the build, contract, and direct-startup steps before GHCR denied the publication token.
  • The Nemotron advisor rerun repeated the workflow’s internal omitted-tool-result error. Both attempts preserved zero canonical findings, while the independent Terra advisor completed successfully. This is an external advisor execution blocker, not a failure in the PR changes; another blind rerun is unlikely to help.

All executable code, image, documentation, DCO, commit-verification, and security checks otherwise pass. The remaining requirements are a successful required advisor check and human approval.

Signed-off-by: San Dang <sdang@nvidia.com>

@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/dockerfile-patch.ts`:
- Around line 119-121: Update the regex in the runtimeUserArgs filter to use
case-insensitive matching so uppercase, lowercase, and mixed-case ARG
instructions are accepted. Add a regression test covering a non-uppercase ARG
instruction and verifying explicit corporate CA configuration succeeds.
🪄 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: c32f5393-958b-4c3c-b99e-49e40a3705ea

📥 Commits

Reviewing files that changed from the base of the PR and between c29f900 and a9e3eaf.

📒 Files selected for processing (3)
  • docs/security/configure-corporate-ca-trust.mdx
  • src/lib/onboard/dockerfile-patch-corporate-ca.test.ts
  • src/lib/onboard/dockerfile-patch.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard/dockerfile-patch-corporate-ca.test.ts
  • docs/security/configure-corporate-ca-trust.mdx

Comment thread src/lib/onboard/dockerfile-patch.ts Outdated
Signed-off-by: San Dang <sdang@nvidia.com>

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Blocking security finding on the latest PR commit a9e3eaf13.

openClawRootStartupArg proves only that the final USER ${NEMOCLAW_MANAGED_IMAGE_RUNTIME_USER} precedes some final ENTRYPOINT. It does not require that entrypoint to be the trusted /usr/local/bin/nemoclaw-start launcher. Corporate-CA patching then rewrites the runtime-user ARG to root.

A custom Dockerfile can therefore satisfy the current shape with a different entrypoint and run its agent command as root. Require the trusted OpenClaw entrypoint (or an equivalent verified step-down contract) before selecting root startup. Add a regression with a different final ENTRYPOINT and assert explicit CA baking rejects it without rewriting the runtime-user ARG.

The current commit-lint failure and pending managed-runtime check are separate hard gates.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/onboard/dockerfile-patch.ts (1)

553-589: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Fail closed when agentName is omitted.

The production flow passes agentName, but PatchStagedDockerfileOptions.agentName is optional. Require the identity or reject CA baking when it is absent, and add a regression test for this path.

🤖 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/dockerfile-patch.ts` around lines 553 - 589, Update the
Dockerfile patch logic around openClawRootStartup and corporateCaArgPattern so
corporate CA baking fails closed when options.agentName is absent, rather than
treating the missing identity as a non-OpenClaw flow. Require a valid agent
identity before applying the CA replacement, preserve the existing OpenClaw
validation behavior, and add a regression test covering omitted agentName.

Source: Coding guidelines

🤖 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.

Outside diff comments:
In `@src/lib/onboard/dockerfile-patch.ts`:
- Around line 553-589: Update the Dockerfile patch logic around
openClawRootStartup and corporateCaArgPattern so corporate CA baking fails
closed when options.agentName is absent, rather than treating the missing
identity as a non-OpenClaw flow. Require a valid agent identity before applying
the CA replacement, preserve the existing OpenClaw validation behavior, and add
a regression test covering omitted agentName.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6e8a7ae8-662a-44c2-b844-4f5cebe0befe

📥 Commits

Reviewing files that changed from the base of the PR and between a9e3eaf and c588b76.

📒 Files selected for processing (3)
  • docs/security/configure-corporate-ca-trust.mdx
  • src/lib/onboard/dockerfile-patch-corporate-ca.test.ts
  • src/lib/onboard/dockerfile-patch.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard/dockerfile-patch-corporate-ca.test.ts
  • docs/security/configure-corporate-ca-trust.mdx

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-review of latest PR commit c588b765d: the previously requested root-startup fix is correctly implemented.

The final-stage contract now requires the exact exec-form ENTRYPOINT ["/usr/local/bin/nemoclaw-start"], preserves the exact case-sensitive build-argument identity while accepting case-insensitive Dockerfile instruction keywords, and rejects a custom entrypoint without rewriting the runtime-user ARG. The new negative test covers the bypass shape. I found no replacement blocker in this delta.

I am not approving yet: base 97ee9ce0b is behind current main, and the full exact-commit security, build, CodeQL, advisor, managed-startup, and CLI check set is still running. My earlier change request is substantively addressed; final approval must wait for those hard gates.

@prekshivyas
prekshivyas dismissed their stale review August 11, 2026 17:38

Addressed in c588b76: the trusted exec-form entrypoint is now required and the bypass regression is present. This dismissal is not approval; exact-commit hard gates remain pending.

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

Copy link
Copy Markdown
Collaborator

Security follow-up review: pass with no new blocker for validated revision 5e7a138de.

The corporate-CA root-startup boundary now fails closed on all reviewed identity paths:

  • OpenClaw root startup requires exactly one final-stage runtime-user argument, the exact runtime-user variable in the final USER, and the trusted one-element exec-form entrypoint for /usr/local/bin/nemoclaw-start.
  • Dockerfile instruction keywords may vary in case, but the managed argument name, user expression, ordering, and trusted entrypoint remain exact.
  • A missing staged agent identity now stops CA baking before any Dockerfile mutation. The production staging flow supplies this identity; the new guard protects alternate or future callers.
  • A different entrypoint, differently cased managed argument name, ambiguous declaration, missing identity, or malformed startup shape cannot select the root-startup rewrite.

No new dependency, network, credential-storage, logging, path-traversal, or unsafe parsing surface was introduced. The CA bundle is a public certificate, the existing encoding and Docker argument sanitization remain in place, and the secret scan passed.

Validation completed:

  • 14 focused corporate-CA tests passed after integrating current main.
  • CLI typecheck and the normal pre-push hook passed.
  • Repository hooks, source/test budgets, and secret scan passed.
  • The documentation writer confirmed the existing corporate-CA page already covers the supported user-facing contract; no additional docs were needed.
  • Both follow-up commits are signed off and shown as Verified by GitHub.

Fresh hosted checks and required reviewer approval remain merge gates; this review does not waive them.

@wscurran wscurran added area: install Install, setup, prerequisites, or uninstall flow area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior platform: container Affects Docker, containerd, Podman, or images labels Aug 11, 2026
@wscurran wscurran added the platform: ubuntu Affects Ubuntu Linux environments label Aug 11, 2026

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the current head, including the fail-closed agent identity guard and corporate CA ownership/startup contract, and found no remaining security or correctness issue. I am withholding approval because this branch does not contain current main; refresh it and rerun required checks so approval can bind to the integrated exact head.

@prekshivyas
prekshivyas merged commit 3c94f77 into main Aug 12, 2026
60 checks passed
@prekshivyas
prekshivyas deleted the fix/root-owned-corporate-ca-8803 branch August 12, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: install Install, setup, prerequisites, or uninstall flow area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior platform: container Affects Docker, containerd, Podman, or images platform: ubuntu Affects Ubuntu Linux environments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu 24.04][Security] merged corporate CA bundle is owned by the sandbox user

5 participants