Skip to content

fix(sandbox): anchor corporate CA for image build TLS - #6845

Merged
cv merged 3 commits into
mainfrom
fix/corporate-ca-build-tls-anchor
Jul 14, 2026
Merged

fix(sandbox): anchor corporate CA for image build TLS#6845
cv merged 3 commits into
mainfrom
fix/corporate-ca-build-tls-anchor

Conversation

@laitingsheng

@laitingsheng laitingsheng commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

The corporate proxy CA baked by the onboard opt-in (#6210) was decoded only late in the sandbox image build — after the OpenClaw/mcporter reinstall path — and NODE_EXTRA_CA_CERTS was never set at build time. Behind a TLS-intercepting corporate proxy the npm audit signatures step then failed to fetch the sigstore TUF root and aborted the build with SELF_SIGNED_CERT_IN_CHAIN. This moves the CA decode ahead of the reinstall path and exports NODE_EXTRA_CA_CERTS for the whole final build stage, so build-time TLS traverses the operator proxy exactly as runtime already does.

Related Issue

Fixes #6839

Changes

  • Dockerfile: moved ARG NEMOCLAW_CORPORATE_CA_B64 and the CA decode/validate RUN to the top of the final stage, so the decoded corporate-ca.pem exists before the OpenClaw/mcporter reinstall RUN (which runs npm audit signatures). The decode block text is unchanged, so the existing decode-guard contract still applies.
  • Dockerfile: added a final-stage ENV NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem. Node ignores a missing file, so this is a no-op when no CA is baked; scripts/nemoclaw-start.sh still overrides it at runtime with the merged OpenShell + corporate bundle. Signature and integrity verification are unchanged — this only adds a transport trust anchor.
  • test/corporate-ca-build-tls-anchor.test.ts: new contract test pinning that the ARG, the decode RUN, and the anchor ENV all precede the reinstall audit signatures step, and that exactly one corporate CA build arg exists (the onboard patch's single replace target). The real failure only reproduces against a full image build behind a TLS-intercepting proxy, so this asserts the shipped build ordering rather than a runtime path — registered as two security source-shape contract exceptions in ci/source-shape-test-budget.json.

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: restores the intended [NemoClaw][DGX Station][Sandbox] Corporate proxy CA not injected into sandbox trust store — external channel TLS fails (Telegram NET:FAIL) #6210 corporate-CA behavior on the image-build path; no new user-facing surface or option is introduced.
  • 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: requesting maintainer review — change is confined to the sandbox image build trust path; it only makes the operator's own public CA (already baked for runtime) available to build-time TLS. Package signature and integrity checks still run end to end.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result: vitest run --project integration test/corporate-ca-build-tls-anchor.test.ts test/corporate-ca-dockerfile-decode.test.ts → 16 passed; vitest run --project cli src/lib/onboard/dockerfile-patch-corporate-ca.test.ts → 6 passed; npm run source-shape:check → cases=0, invalid=0.
  • 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: Tinson Lai tinsonl@nvidia.com

Summary by CodeRabbit

  • New Features

    • Improved optional corporate proxy CA handling by consolidating certificate processing earlier in the runtime image flow, anchoring TLS trust consistently for both build-time and runtime.
  • Tests

    • Added a new test suite to verify the corporate CA build argument is declared exactly once.
    • Added checks that CA decoding and TLS trust export occur in the required order relative to audit/signature steps.
  • Chores

    • Updated the source-shape test budget exceptions to allow the new TLS ordering validations.

The corporate proxy CA was decoded only after the OpenClaw/mcporter reinstall
path, and NODE_EXTRA_CA_CERTS was never set at build time. Behind a
TLS-intercepting corporate proxy the npm audit signatures step then failed to
fetch the sigstore TUF root, aborting the build with SELF_SIGNED_CERT_IN_CHAIN.
Decode the CA early in the final stage and export NODE_EXTRA_CA_CERTS so
build-time TLS traverses the operator proxy. Signature and integrity
verification still run end to end; this only adds a transport trust anchor.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@laitingsheng laitingsheng self-assigned this Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The Dockerfile provisions an optional corporate proxy CA before build-time TLS operations, exports NODE_EXTRA_CA_CERTS, and validates the arrangement with a new source-shape test and associated budget exceptions.

Changes

Corporate CA build-time TLS

Layer / File(s) Summary
Build-time CA anchor
Dockerfile
Decodes and validates the optional corporate CA into a protected PEM, exports NODE_EXTRA_CA_CERTS, and removes the previous later duplicate setup.
Dockerfile ordering validation
test/corporate-ca-build-tls-anchor.test.ts, ci/source-shape-test-budget.json
Tests unique CA argument declaration and verifies CA setup precedes mcporter-runtime audit signatures; records the source-shape exceptions.

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

Sequence Diagram(s)

sequenceDiagram
  participant DockerBuild
  participant CorporateCABundle
  participant AuditSignatures
  DockerBuild->>CorporateCABundle: Decode and validate corporate CA
  CorporateCABundle-->>DockerBuild: Export NODE_EXTRA_CA_CERTS
  DockerBuild->>AuditSignatures: Run audit-signature verification
Loading

Suggested labels: platform: container, area: sandbox

Suggested reviewers: cv

🚥 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 title clearly summarizes the main change: anchoring the corporate CA for build-time TLS in the sandbox image.
Linked Issues check ✅ Passed The Dockerfile now decodes the corporate CA early and exports NODE_EXTRA_CA_CERTS before reinstall/audit steps, matching #6839.
Out of Scope Changes check ✅ Passed The test and CI budget updates support the Dockerfile change and stay within the build-time TLS anchoring scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/corporate-ca-build-tls-anchor

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

@github-code-quality

github-code-quality Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the fix/corporate-ca-bui... branch remains at 79%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main 33d55b0 fix/corporate-ca-bui... d967cf3 +/-
src/lib/securit...ntial-filter.ts 99% 98% -1%
src/lib/state/m...-acquisition.ts 89% 90% +1%
src/lib/state/gateway.ts 91% 93% +2%

Updated July 14, 2026 13:20 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / high confidence
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions
Status: Canonical ledger: 0 blocker(s), 1 warning(s), 0 suggestion(s).

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; severity counts match.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-onboard

1 optional E2E recommendation
  • rebuild-openclaw
1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Exercise build-time CA trust on the reinstall path

  • Location: test/corporate-ca-build-tls-anchor.test.ts:19
  • Category: tests
  • Problem: The new test verifies only Dockerfile substring ordering. It does not execute an image build with a supplied corporate CA on the `USE_REVIEWED_BASE_RUNTIME=0` branch, where `npm audit signatures` makes the TLS request this change is intended to unblock.
  • Impact: A source-order test can pass while the actual Node signature-audit fetch still rejects a TLS-intercepting corporate proxy, leaving custom or stale-base rebuilds unable to complete.
  • Recommendation: Add the smallest runtime build regression that supplies a corporate CA, forces the OpenClaw/mcporter reinstall branch, and verifies the signature-audit TLS operation succeeds through an intercepting test proxy.
  • Verification: Inspect a checked-in test that builds the Dockerfile with a corporate CA and a forced non-reviewed base, then observes the audit-signatures TLS consumer complete through a test TLS-intercepting proxy.
  • Test coverage: A runtime Docker build test that forces `USE_REVIEWED_BASE_RUNTIME=0`, injects a test corporate CA and intercepting proxy, and asserts `npm audit signatures` succeeds rather than failing with `SELF_SIGNED_CERT_IN_CHAIN`.
  • Evidence: test/corporate-ca-build-tls-anchor.test.ts:19-39 uses `indexOf` and relative-order assertions only. Dockerfile's reinstall branch invokes `npm --prefix /usr/local/lib/nemoclaw/mcporter-runtime audit signatures` when exact reviewed-base provenance is unavailable. test/e2e/live/cloud-onboard.test.ts covers a corporate-CA runtime merge but does not establish the reinstall branch's build-time TLS request.

Workflow run details

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

@cv
cv enabled auto-merge (squash) July 14, 2026 09:56
@laitingsheng laitingsheng added area: packaging Packages, images, registries, installers, or distribution area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression NV QA Bugs found by the NVIDIA QA Team labels Jul 14, 2026
@laitingsheng laitingsheng removed their assignment Jul 14, 2026
@cv cv added the v0.0.83 label Jul 14, 2026
Moving the corporate CA decode earlier in the runtime stage put it
ahead of the AWS_EC2_METADATA_DISABLED and JITI_FS_CACHE hardening,
making it the first RUN before that hardening took effect. Reorder so
the hardening ENV lines stay first; the CA decode still lands well
before the OpenClaw/mcporter reinstall step it targets.

Signed-off-by: Tinson Lai <tinsonl@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.

Caution

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

⚠️ Outside diff range comments (2)
Dockerfile (2)

98-106: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Protect /usr/local/share/nemoclaw before writing the CA file. A pre-existing symlink or hardlink in the base image can redirect this root-owned write to another file; the later chown/chmod do not prevent that overwrite. Create and lock down the directory first, write to a temp file inside it, then rename it into place.

🤖 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 `@Dockerfile` around lines 98 - 106, Update the CA installation block around
/usr/local/share/nemoclaw/corporate-ca.pem to secure the directory before any
write, including rejecting or removing unsafe pre-existing links as appropriate.
Decode and validate the certificate bundle into a temporary file inside that
directory, then atomically rename it to corporate-ca.pem before applying
ownership and permissions; do not write directly to the final path.

Source: Path instructions


88-116: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Clear inherited corporate CA when the build arg is empty.

If /usr/local/share/nemoclaw/corporate-ca.pem already exists in the base image, the empty-arg path leaves it in place while NODE_EXTRA_CA_CERTS still points at it. Remove the file when NEMOCLAW_CORPORATE_CA_B64 is unset, and add a regression test for an inherited CA 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 `@Dockerfile` around lines 88 - 116, The Dockerfile’s empty
NEMOCLAW_CORPORATE_CA_B64 path must remove any inherited corporate CA before
setting NODE_EXTRA_CA_CERTS. Update the RUN block around
NEMOCLAW_CORPORATE_CA_B64 to delete /usr/local/share/nemoclaw/corporate-ca.pem
when the argument is empty, while preserving the existing decode and validation
flow for non-empty values. Add a regression test covering a base image with an
inherited CA file and an unset build argument.

Source: Path instructions

🤖 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 `@Dockerfile`:
- Around line 98-106: Update the CA installation block around
/usr/local/share/nemoclaw/corporate-ca.pem to secure the directory before any
write, including rejecting or removing unsafe pre-existing links as appropriate.
Decode and validate the certificate bundle into a temporary file inside that
directory, then atomically rename it to corporate-ca.pem before applying
ownership and permissions; do not write directly to the final path.
- Around line 88-116: The Dockerfile’s empty NEMOCLAW_CORPORATE_CA_B64 path must
remove any inherited corporate CA before setting NODE_EXTRA_CA_CERTS. Update the
RUN block around NEMOCLAW_CORPORATE_CA_B64 to delete
/usr/local/share/nemoclaw/corporate-ca.pem when the argument is empty, while
preserving the existing decode and validation flow for non-empty values. Add a
regression test covering a base image with an inherited CA file and an unset
build argument.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6da91b9c-fc39-4245-8586-1eefb3d3b818

📥 Commits

Reviewing files that changed from the base of the PR and between 31fdd97 and d967cf3.

📒 Files selected for processing (1)
  • Dockerfile

@cv
cv merged commit 20130dd into main Jul 14, 2026
84 checks passed
@cv
cv deleted the fix/corporate-ca-build-tls-anchor branch July 14, 2026 13:26
jyaunches added a commit that referenced this pull request Jul 14, 2026
## Summary

Add v0.0.83 release notes to `docs/about/release-notes.mdx` for pre-tag
release prep.

## Source Summary

- #6773 -> `docs/about/release-notes.mdx`: Shared inference route
changes are explicit and fail-safe; status shows recorded route, live
route, and drift.
- #6875 -> `docs/about/release-notes.mdx`: DGX Station GB300 express
setup restored; vLLM storage preflight narrowed.
- #6770 -> `docs/about/release-notes.mdx`: Risky Spark vLLM server
warning during onboarding.
- #6856 -> `docs/about/release-notes.mdx`: Re-onboard reuse preserves
tier-default brave/tavily presets.
- #6867 -> `docs/about/release-notes.mdx`: Unreachable custom endpoint
routed through transport-recovery path.
- #6860 -> `docs/about/release-notes.mdx`: Rebuild preflight uses
model-aware token field for o-series/GPT-5.
- #6845 -> `docs/about/release-notes.mdx`: Corporate CA anchored for
image build TLS.
- #6833 -> `docs/about/release-notes.mdx`: SSH ControlMaster-delegated
forwards recognized in fallback.
- #6837 -> `docs/about/release-notes.mdx`: Hermes light skin writes via
stdin on macOS.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [x] 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:
- [x] Tests not applicable — justification: doc-only release notes
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed
- [ ] Non-success, skipped, or missing CI check accepted by maintainer

## Verification
- [x] PR description includes the DCO sign-off declaration and every
commit appears as Verified in GitHub
- [x] Normal pre-commit, commit-msg, and pre-push hooks passed
- [x] `npm run docs` passes with 0 errors

Signed-off-by: Jessica Yaunches <jyaunches@nvidia.com>

Signed-off-by: Jessica Yaunches <jyaunches@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: packaging Packages, images, registries, installers, or distribution area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression NV QA Bugs found by the NVIDIA QA Team

Projects

None yet

3 participants