Skip to content

refactor(onboard): extract dockerfile patch flow#5154

Merged
cv merged 38 commits into
mainfrom
codex/onboard-dockerfile-patch-flow
Jun 11, 2026
Merged

refactor(onboard): extract dockerfile patch flow#5154
cv merged 38 commits into
mainfrom
codex/onboard-dockerfile-patch-flow

Conversation

@cv

@cv cv commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Extracts the createSandbox Dockerfile patch flow into a focused helper. This keeps base-image resolution, cached-base warnings, Docker-driver GPU network preservation, build id allocation, and patchStagedDockerfile invocation together while preserving the existing sandbox create path.

Related Issue

Refs #3802

Changes

  • Added prepareSandboxDockerfilePatch in src/lib/onboard/sandbox-dockerfile-patch-flow.ts.
  • Replaced the inline base-image resolution, Docker GPU network preservation, and Dockerfile patch block in createSandbox with the new helper.
  • Hardened staged Dockerfile patching so read/write reopens use O_NOFOLLOW, validate regular files, and truncate only after descriptor validation.
  • Added focused coverage for digest pinning, agent-staged Dockerfile base-image skip behavior, selected-agent plus custom-Dockerfile resolution, cached-base fallback warning, unavailable-base recovery warning, the patched Dockerfile argument envelope, symlink refusal, non-regular path refusal, and read/write swap guards.

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)

Verification

Local targeted checks run:

  • npx @biomejs/biome format --write src/lib/onboard.ts src/lib/onboard/sandbox-dockerfile-patch-flow.ts src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts src/lib/onboard/dockerfile-patch.ts src/lib/onboard/dockerfile-patch-security.test.ts
  • npx @biomejs/biome lint src/lib/onboard.ts src/lib/onboard/sandbox-dockerfile-patch-flow.ts src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts src/lib/onboard/dockerfile-patch.ts src/lib/onboard/dockerfile-patch-security.test.ts
  • npm run build:cli
  • npm run typecheck:cli
  • npx vitest run src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts src/lib/onboard/dockerfile-patch.test.ts src/lib/onboard/dockerfile-patch-security.test.ts src/lib/onboard/dockerfile-patch-extra-agents.test.ts src/lib/onboard/docker-gpu-local-inference.test.ts test/onboard.test.ts
  • git diff --check

GitHub PR checks on b793d635beda48a752c666fab0d7e2a7407e4bf8:

  • Standard PR checks green, including CodeQL, ShellCheck, build/typecheck, CLI shards, plugin tests, installer integration, macOS E2E, commit-lint, DCO, check-hash, growth guardrails, and maintainer edits.
  • PR review advisor run 27289383817 reported no needs-attention / worth-checking / nice-idea findings in the job log. Its PR comment update hit a GitHub REST 401, so the visible advisor comment may be stale.

Live validation:

Local broad-hook note:

  • Full npx prek run --all-files remains blocked locally by the unrelated test/release-latest-tag.test.ts fixture commit signing failure (/home/cvillela/.ssh/git-signing-key.pub missing private key). This PR does not touch that release test file.

  • npx prek run --all-files passes

  • npm test passes

  • Tests added or updated for new or changed behavior

  • No secrets, API keys, or credentials committed

  • Docs updated for user-facing behavior changes

  • 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: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Added safeguards against symlink-based vulnerabilities in Dockerfile patching operations.
  • Tests

    • Added test coverage for Dockerfile patching security measures, including symlink detection and regular file validation.
    • Added tests for sandbox Dockerfile preparation workflows including base image resolution and patching.

@cv cv self-assigned this Jun 10, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jun 10, 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: fd30db4f-4779-465c-a70d-093eb02903a8

📥 Commits

Reviewing files that changed from the base of the PR and between ffb1111 and d649b2b.

📒 Files selected for processing (5)
  • src/lib/onboard.ts
  • src/lib/onboard/dockerfile-patch-security.test.ts
  • src/lib/onboard/dockerfile-patch.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.ts

📝 Walkthrough

Walkthrough

This PR refactors sandbox Dockerfile patching to improve security and reusability. Symlink-safe file operations with O_NOFOLLOW are added to patchStagedDockerfile. Sandbox patch preparation logic is extracted into a new prepareSandboxDockerfilePatch flow module with optional base-image resolution and dependency injection. The flow is integrated into createSandbox, replacing the previous inline implementation.

Changes

Sandbox Dockerfile Patching Refactor

Layer / File(s) Summary
Symlink-Safe Dockerfile Operations
src/lib/onboard/dockerfile-patch.ts, src/lib/onboard/dockerfile-patch-security.test.ts
Added O_NOFOLLOW-based file operation helpers to reject symlinks and non-regular files. patchStagedDockerfile now reads and writes Dockerfile via safe file descriptors with proper cleanup. Security tests verify refusal on symlinks, directories, and swap-time attacks.
Sandbox Dockerfile Patch Flow Module
src/lib/onboard/sandbox-dockerfile-patch-flow.ts, src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts
New prepareSandboxDockerfilePatch flow encapsulates base-image digest resolution (conditional on agent and custom Dockerfile), GPU patch enforcement, and staged Dockerfile patching. Dependency-injection wrappers delegate to underlying modules. Tests cover successful resolution, default Dockerfile skip, custom Dockerfile resolution, and fallback warnings when resolution fails or base image is unavailable.
Integration with createSandbox
src/lib/onboard.ts
Imported new sandboxDockerfilePatchFlow module and replaced inline patching logic with prepareSandboxDockerfilePatch call. Removed unused dockerImageInspect import and thread returned buildId for downstream use.

Sequence Diagram

sequenceDiagram
  participant createSandbox
  participant prepareSandboxDockerfilePatch
  participant pullAndResolveBaseImageDigest
  participant inspectDockerImage
  participant enforceDockerGpuPatchPreserveNetwork
  participant patchStagedDockerfile
  
  createSandbox->>prepareSandboxDockerfilePatch: call with stagedDockerfile, agent, provider, etc.
  alt agent present and custom Dockerfile
    prepareSandboxDockerfilePatch->>pullAndResolveBaseImageDigest: resolve base image digest
    alt resolution succeeds
      pullAndResolveBaseImageDigest-->>prepareSandboxDockerfilePatch: return resolved digest
      prepareSandboxDockerfilePatch->>inspectDockerImage: verify image available
    else resolution fails
      pullAndResolveBaseImageDigest-->>prepareSandboxDockerfilePatch: error
      prepareSandboxDockerfilePatch->>inspectDockerImage: check :latest fallback
      alt :latest exists
        inspectDockerImage-->>prepareSandboxDockerfilePatch: cached
        prepareSandboxDockerfilePatch-->>prepareSandboxDockerfilePatch: warn cached fallback
      else :latest missing
        prepareSandboxDockerfilePatch-->>prepareSandboxDockerfilePatch: warn with docker pull command
      end
    end
  else default Dockerfile or no agent
    prepareSandboxDockerfilePatch-->>prepareSandboxDockerfilePatch: skip resolution
  end
  prepareSandboxDockerfilePatch->>enforceDockerGpuPatchPreserveNetwork: enforce GPU patch
  prepareSandboxDockerfilePatch->>patchStagedDockerfile: patch with resolved base ref or null
  patchStagedDockerfile-->>prepareSandboxDockerfilePatch: return patched result
  prepareSandboxDockerfilePatch-->>createSandbox: return { buildId, resolvedBaseImage }
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested Labels

area: sandbox

Suggested Reviewers

  • prekshivyas

Poem

🐰 A rabbit hops through symlinks with care,
With O_NOFOLLOW flags floating in air,
Dockerfile patching flows, safe and refine,
The sandbox grows stronger, line by line!
hop hop

🚥 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 accurately summarizes the main change: extracting the Dockerfile patch flow from createSandbox into a dedicated helper function (prepareSandboxDockerfilePatch).
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/onboard-dockerfile-patch-flow

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

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: openclaw-onboard-security-posture-e2e, hermes-e2e
Optional E2E: openclaw-plugin-runtime-exdev-e2e, gpu-e2e, credential-sanitization-e2e

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

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

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • openclaw-onboard-security-posture-e2e (high): High-signal required coverage for the changed OpenClaw onboarding path: runs install/onboard, patches the staged Dockerfile, creates the sandbox, verifies inference.local/OpenClaw turn completion, and enables sandbox security-posture assertions.
  • hermes-e2e (high): The new helper has agent-specific behavior that skips base-image resolution for agent default Dockerfiles and still patches Hermes/tool-gateway ARGs; run the real Hermes assistant onboard/runtime flow to cover that branch.

Optional E2E

  • openclaw-plugin-runtime-exdev-e2e (medium): Useful adjacent confidence for the --from custom Dockerfile branch, which now resolves/pins the sandbox base image and patches the staged Dockerfile through the new helper before creating a live OpenClaw sandbox.
  • gpu-e2e (very high): Optional because of GPU runner cost, but relevant: this PR moved the Docker GPU local-inference network-preservation call into the helper used before Dockerfile patching and sandbox create.
  • credential-sanitization-e2e (high): Adjacent security regression coverage for symlink-safe host-file handling and credential/sandbox boundary checks, though it does not directly exercise the new staged-Dockerfile symlink guard.

New E2E recommendations

  • Dockerfile patch security (high): Existing new coverage is unit-level. There is no live CLI/E2E negative-path test that plants a symlinked Dockerfile in an onboard/custom-Dockerfile flow and proves the target file is not modified.
    • Suggested test: Add a live or hermetic CLI E2E that runs nemoclaw onboard --from <symlinked Dockerfile> or equivalent staged-context setup, expects a clear refusal, and verifies the symlink target remains unchanged.
  • base image pinning (medium): The base-image pull/resolve/pin logic was extracted from createSandbox into a helper, but existing live E2E does not explicitly assert the patched Dockerfile/build uses the freshly resolved sandbox-base digest for custom Dockerfiles.
    • Suggested test: Add an E2E assertion around a custom --from onboard that captures the resolved sandbox-base digest and verifies the staged Dockerfile/build log uses that pinned ref instead of stale :latest.

Dispatch hint

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

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: ubuntu-repo-cloud-openclaw
Optional Vitest E2E scenarios: None

Dispatch required Vitest E2E scenarios:

  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required Vitest E2E scenarios

  • ubuntu-repo-cloud-openclaw: The PR refactors the core onboarding sandbox Dockerfile patch path, including base-image pinning, Dockerfile mutation safety, and GPU-network preservation orchestration. The live-supported Ubuntu repo cloud OpenClaw scenario exercises the standard Docker-backed onboarding/create flow that reaches this patching surface.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw

Optional Vitest E2E scenarios

  • None.

Relevant changed files

  • src/lib/onboard.ts
  • src/lib/onboard/dockerfile-patch.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.ts
  • src/lib/onboard/dockerfile-patch-security.test.ts
  • src/lib/onboard/sandbox-dockerfile-patch-flow.test.ts

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

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

Consider writing more tests for
  • **Runtime validation** — Runtime/integration: default onboard build writes a staged Dockerfile whose ARG BASE_IMAGE uses the resolved digest before openshell sandbox create.. Unit coverage is strong for the extracted helper and Dockerfile path guards, but the changed code participates in real Docker/OpenShell sandbox creation and Docker-driver GPU infrastructure where behavior depends on runtime state.
  • **Runtime validation** — Runtime/integration: selected agent with custom --from resolves and passes the base-image ref into the staged Dockerfile patch.. Unit coverage is strong for the extracted helper and Dockerfile path guards, but the changed code participates in real Docker/OpenShell sandbox creation and Docker-driver GPU infrastructure where behavior depends on runtime state.
  • **Runtime validation** — Runtime/integration: Docker-driver GPU local-inference host-network opt-in is downgraded to preserve bridge networking before sandbox create consumes the GPU patch network mode.. Unit coverage is strong for the extracted helper and Dockerfile path guards, but the changed code participates in real Docker/OpenShell sandbox creation and Docker-driver GPU infrastructure where behavior depends on runtime state.
  • **Runtime validation** — Runtime/integration: offline/no-local-base path prints manual docker pull recovery guidance before the Docker build failure.. Unit coverage is strong for the extracted helper and Dockerfile path guards, but the changed code participates in real Docker/OpenShell sandbox creation and Docker-driver GPU infrastructure where behavior depends on runtime state.
  • **Runtime validation** — Platform/unit if native Windows onboard is supported: patchStagedDockerfile fails closed with an actionable error when fs.constants.O_NOFOLLOW is unavailable.. Unit coverage is strong for the extracted helper and Dockerfile path guards, but the changed code participates in real Docker/OpenShell sandbox creation and Docker-driver GPU infrastructure where behavior depends on runtime state.

Workflow run details

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

Comment thread src/lib/onboard/dockerfile-patch.ts Fixed
Comment thread src/lib/onboard/dockerfile-patch.ts Fixed
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 27289825954
Target ref: codex/onboard-dockerfile-patch-flow
Workflow ref: main
Requested jobs: cloud-onboard-e2e,openclaw-plugin-runtime-exdev-e2e,openclaw-onboard-security-posture-e2e
Summary: 2 passed, 0 failed, 0 skipped

Job Result
cloud-onboard-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success
openclaw-plugin-runtime-exdev-e2e ❓ not reported

Missing requested jobs: openclaw-plugin-runtime-exdev-e2e. The reporting workflow needs to include these jobs.

@cv cv marked this pull request as ready for review June 11, 2026 16:56
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 27363626432
Target ref: 491a555ac6ddc560bd91bf88157e263553148416
Workflow ref: codex/onboard-build-patch-config-flow
Requested jobs: cloud-onboard-e2e,openclaw-onboard-security-posture-e2e
Summary: 1 passed, 1 failed, 0 skipped

Job Result
cloud-onboard-e2e ❌ failure
openclaw-onboard-security-posture-e2e ✅ success

Failed jobs: cloud-onboard-e2e. Check run artifacts for logs.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 27363626432
Target ref: 491a555ac6ddc560bd91bf88157e263553148416
Workflow ref: codex/onboard-build-patch-config-flow
Requested jobs: cloud-onboard-e2e,openclaw-onboard-security-posture-e2e
Summary: 1 passed, 1 failed, 0 skipped

Job Result
cloud-onboard-e2e ❌ failure
openclaw-onboard-security-posture-e2e ✅ success

Failed jobs: cloud-onboard-e2e. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 27363626432
Target ref: 491a555ac6ddc560bd91bf88157e263553148416
Workflow ref: codex/onboard-build-patch-config-flow
Requested jobs: cloud-onboard-e2e,openclaw-onboard-security-posture-e2e
Summary: 2 passed, 0 failed, 0 skipped

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

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 27376842024
Target ref: d183ff0a497ca335500e92596b50817deaf144b5
Workflow ref: codex/onboard-build-patch-config-flow
Requested jobs: cloud-onboard-e2e,cloud-inference-e2e,openclaw-onboard-security-posture-e2e
Summary: 1 passed, 2 failed, 0 cancelled, 0 skipped

Job Result
cloud-inference-e2e ✅ success
cloud-onboard-e2e ❌ failure
openclaw-onboard-security-posture-e2e ❌ failure

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

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 27376842024
Target ref: d183ff0a497ca335500e92596b50817deaf144b5
Workflow ref: codex/onboard-build-patch-config-flow
Requested jobs: cloud-onboard-e2e,cloud-inference-e2e,openclaw-onboard-security-posture-e2e
Summary: 1 passed, 2 failed, 0 cancelled, 0 skipped

Job Result
cloud-inference-e2e ✅ success
cloud-onboard-e2e ❌ failure
openclaw-onboard-security-posture-e2e ❌ failure

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

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 27376842024
Target ref: d183ff0a497ca335500e92596b50817deaf144b5
Workflow ref: codex/onboard-build-patch-config-flow
Requested jobs: cloud-onboard-e2e,cloud-inference-e2e,openclaw-onboard-security-posture-e2e
Summary: 3 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-inference-e2e ✅ success
cloud-onboard-e2e ✅ success
openclaw-onboard-security-posture-e2e ✅ success

Base automatically changed from codex/onboard-build-patch-config-flow to main June 11, 2026 21:58
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

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

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

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

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

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

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

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

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ❌ Some jobs failed

Run: 27380825270
Target ref: d649b2b91705e58fd9d82c1b001b8be93e2b5619
Workflow ref: main
Requested jobs: openclaw-onboard-security-posture-e2e,hermes-e2e
Summary: 1 passed, 1 failed, 0 cancelled, 0 skipped

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

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

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

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

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

@cv cv merged commit 27ae4c3 into main Jun 11, 2026
99 of 102 checks passed
@cv cv deleted the codex/onboard-dockerfile-patch-flow branch June 11, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow refactor PR restructures code without intended behavior change v0.0.64 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants