Skip to content

fix(revert): fix(blueprint): default OpenClaw fetch guard to sandbox proxy - #6051

Merged
cv merged 1 commit into
mainfrom
revert-5713-fix/openclaw-fetch-guard-default-proxy
Jun 30, 2026
Merged

fix(revert): fix(blueprint): default OpenClaw fetch guard to sandbox proxy#6051
cv merged 1 commit into
mainfrom
revert-5713-fix/openclaw-fetch-guard-default-proxy

Conversation

@cv

@cv cv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Reverts #5713, merged by accident

Summary by CodeRabbit

  • Bug Fixes

    • Improved sandbox proxy handling so unconfigured strict network requests are routed correctly in OpenShell environments.
    • Added safer cron preflight behavior to avoid breaking DNS-pinned strict-mode runs in proxy-only sandboxes.
  • Chores

    • Removed an unused runtime verification step and simplified the build process.
    • Updated related automation and test coverage to match the new proxy and patching behavior.

Signed-off-by: Carlos Villela cv@lixo.org

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Removes the build-time fetch-guard runtime verifier script and all associated Dockerfile build steps, staging, and test references. Rewrites Dockerfile Patch 4 to route unconfigured STRICT fetches through the sandbox egress proxy via a managed-proxy activation condition. Adds Patch 6 to rewrite cron model-provider preflight callsites to use mode: "trusted_env_proxy". Updates regression tests accordingly.

Changes

Fetch-guard verifier removal and patch rewrites

Layer / File(s) Summary
Remove fetch-guard verifier from build and staging
Dockerfile, src/lib/sandbox/build-context.ts, test/sandbox-build-context.test.ts, scripts/verify-openclaw-fetch-guard-runtime.ts
Removes verifier compilation from the builder stage, runtime copy/chmod, chained execution in the tool-catalog step, and staging of the verifier script from build-context logic and tests. Adds staging of patch-openclaw-chat-send.js in its place.
Patch 4 rewrite: managed-proxy strict-fetch activation
Dockerfile, test/fetch-guard-patch-regression.test.ts
Replaces the resolveGuardedFetchMode default-mode patch with a managed-proxy activation condition gated on OPENSHELL_SANDBOX=1 and absence of explicit dispatcherPolicy. Updates the reviewed shape constant to canUseManagedProxy, removes old guarded-mode-resolver assertions, and adds behavioral tests covering sandbox-only routing, explicit-policy preservation, and gate-drift fail-closed behavior.
Patch 6: cron preflight trusted_env_proxy rewrite
Dockerfile, test/fetch-guard-patch-regression.test.ts
Adds Patch 6 to the OpenClaw dist patching script to rewrite cron-model-provider-preflight callsites to mode: "trusted_env_proxy". Tests add reviewedCronPreflightFixture, writeNeighbouringFetchGuardFixtures, idempotency checks, skip-when-absent coverage, and failure modes for missing fetch helper, missing policy helper, and ambiguous multi-callsite audit context.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 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
Title check ✅ Passed The title matches the main change area: OpenClaw fetch-guard behavior in sandbox proxy mode, and it is framed as a revert.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 revert-5713-fix/openclaw-fetch-guard-default-proxy

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

@github-code-quality

github-code-quality Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the revert-5713-fix/open... branch is 96%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main revert-5713-fix/open... 7119b6f +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the revert-5713-fix/open... branch is 68%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main revert-5713-fix/open... 7119b6f +/-
src/lib/actions...all/run-plan.ts 80%
src/lib/state/o...oard-session.ts 79%
src/lib/actions...dbox/rebuild.ts 74%
src/lib/state/sandbox.ts 72%
src/lib/shields/index.ts 70%
src/lib/onboard/preflight.ts 69%
src/lib/actions...licy-channel.ts 60%
src/lib/onboard...er-gpu-patch.ts 59%
src/lib/policy/index.ts 52%
src/lib/onboard.ts 20%

Updated June 30, 2026 09:01 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@cv cv added the v0.0.71 label Jun 30, 2026
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Changes requested

Merge posture: Do not merge yet
Primary next action: Resolve or justify PRA-1: Source-of-truth review needed: Dockerfile Patch 4 managed-proxy activation for unconfigured strict fetches.
Open items: 0 required · 3 warnings · 0 suggestions · 7 test follow-ups
Top item: Restore runtime verification for patched fetch-guard SSRF behavior

Action checklist

  • PRA-1 Resolve or justify: Source-of-truth review needed: Dockerfile Patch 4 managed-proxy activation for unconfigured strict fetches
  • PRA-2 Resolve or justify: Source-of-truth review needed: Dockerfile Patch 6 cron model-provider preflight trusted-env-proxy injection
  • PRA-3 Resolve or justify: Restore behavioral runtime verification for the patched OpenClaw fetch guard in scripts/verify-openclaw-fetch-guard-runtime.ts:1
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Acceptance clause
  • PRA-T6 Add or justify test follow-up: Dockerfile Patch 4 managed-proxy activation for unconfigured strict fetches
  • PRA-T7 Add or justify test follow-up: Dockerfile Patch 6 cron model-provider preflight trusted-env-proxy injection

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-3 Resolve/justify security scripts/verify-openclaw-fetch-guard-runtime.ts:1 Keep the narrower Patch 4/Patch 6 behavior if intended, but restore or replace the deleted runtime verifier so the Docker build (or an equivalent targeted test) imports the patched compiled dist and asserts the real fetch guard contract after all Dockerfile patches are applied.
Review findings by urgency: 0 required fixes, 3 items to resolve/justify, 0 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: Dockerfile Patch 4 managed-proxy activation for unconfigured strict fetches

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Fixture tests cover the boolean managed-proxy gate, explicit dispatcher-policy preservation, outside-sandbox behavior, and drift fail-closed behavior, but they do not import the final patched OpenClaw dist or verify actual dispatcher and SSRF behavior.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Dockerfile replaces `const canUseManagedProxy = mode === GUARDED_FETCH_MODE.STRICT && isManagedProxyActive() && hasProxyEnvConfigured();` with a condition that also accepts `process.env.OPENSHELL_SANDBOX === "1" && !params.dispatcherPolicy`.

PRA-2 Resolve/justify — Source-of-truth review needed: Dockerfile Patch 6 cron model-provider preflight trusted-env-proxy injection

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: New tests cover reviewed single-callsite patching, idempotence, absence, missing helper, missing policy helper, and ambiguous audit literals. They do not prove at runtime that the patched preflight call still uses the expected policy argument or that private redirects/targets remain blocked by the actual compiled fetch guard.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Dockerfile Patch 6 greps for `cron-model-provider-preflight`, requires one audit literal plus file-level `fetchWithSsrFGuard` and `buildLocalProviderSsrFPolicy`, then sed-injects `mode: "trusted_env_proxy"` before the audit context.

PRA-3 Resolve/justify — Restore behavioral runtime verification for the patched OpenClaw fetch guard

  • Location: scripts/verify-openclaw-fetch-guard-runtime.ts:1
  • Category: security
  • Problem: This PR deletes the build-time verifier and removes the Dockerfile step that imported the final patched OpenClaw dist to exercise `fetchWithSsrFGuard`. The replacement tests validate sed rewrites and simplified fixtures, but they no longer prove that the actual compiled OpenClaw module in the image routes the Google Chat cert fetch through the proxy without local DNS while still blocking loopback/private/link-local targets and metadata redirects.
  • Impact: A drift in OpenClaw's compiled fetch guard, redirect handling, dispatcher selection, or policy plumbing could pass the current fixture/string tests and ship in the sandbox image as an SSRF or proxy-policy regression. This is especially sensitive because the changed Dockerfile code directly modifies sandbox egress and SSRF guard behavior.
  • Recommended action: Keep the narrower Patch 4/Patch 6 behavior if intended, but restore or replace the deleted runtime verifier so the Docker build (or an equivalent targeted test) imports the patched compiled dist and asserts the real fetch guard contract after all Dockerfile patches are applied.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read the deleted `scripts/verify-openclaw-fetch-guard-runtime.ts` and compare it with the Dockerfile removal of `node /usr/local/lib/nemoclaw/verify-openclaw-fetch-guard-runtime.mjs`; then inspect `test/fetch-guard-patch-regression.test.ts` around the new managed-proxy and Patch 6 fixture tests to confirm they do not import the real patched OpenClaw dist or exercise redirect re-checks.
  • Missing regression test: Add a compiled-runtime fetch-guard verification that imports the patched OpenClaw dist and proves: an unconfigured strict Google Chat cert URL uses the env proxy without local DNS; `localhost`, `127.0.0.1`, `10.0.0.1`, `::1`, `fe80::1`, `fd00::1`, and `169.254.169.254` are rejected before fetch; a redirect from an allowed public URL to `169.254.169.254` is re-checked and blocked; and the cron model-provider preflight path uses `trusted_env_proxy` for `inference.local` while preserving its hostname allowlist policy.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read the deleted `scripts/verify-openclaw-fetch-guard-runtime.ts` and compare it with the Dockerfile removal of `node /usr/local/lib/nemoclaw/verify-openclaw-fetch-guard-runtime.mjs`; then inspect `test/fetch-guard-patch-regression.test.ts` around the new managed-proxy and Patch 6 fixture tests to confirm they do not import the real patched OpenClaw dist or exercise redirect re-checks.
  • Evidence: The diff deletes `scripts/verify-openclaw-fetch-guard-runtime.ts`, removes it from optimized build-context staging, removes its Dockerfile build/copy/chmod steps, and changes the final patch layer from `patch-openclaw-tool-catalog.js && node ...verify-openclaw-fetch-guard-runtime.mjs` to only `patch-openclaw-tool-catalog.js`.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

  • None.
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Import the final patched OpenClaw dist and verify an unconfigured strict Google Chat certificate fetch uses the env proxy dispatcher without invoking local DNS.. The changed surfaces are sandbox/runtime/infrastructure trust-boundary code (`Dockerfile`, deleted runtime verifier, and build-context staging). Existing changed tests provide useful fixture and shape coverage, but the PR removes the only test that exercised the final patched OpenClaw fetch guard module behavior.
  • PRA-T2 Runtime validation — Import the final patched OpenClaw dist and verify loopback, private IPv4, IPv6 loopback, IPv6 link-local, IPv6 unique-local, and metadata IP targets are rejected before fetch.. The changed surfaces are sandbox/runtime/infrastructure trust-boundary code (`Dockerfile`, deleted runtime verifier, and build-context staging). Existing changed tests provide useful fixture and shape coverage, but the PR removes the only test that exercised the final patched OpenClaw fetch guard module behavior.
  • PRA-T3 Runtime validation — Import the final patched OpenClaw dist and verify a redirect from an allowed public URL to `http://169.254.169.254/latest/meta-data\` is re-checked and blocked.. The changed surfaces are sandbox/runtime/infrastructure trust-boundary code (`Dockerfile`, deleted runtime verifier, and build-context staging). Existing changed tests provide useful fixture and shape coverage, but the PR removes the only test that exercised the final patched OpenClaw fetch guard module behavior.
  • PRA-T4 Runtime validation — Exercise the patched cron model-provider preflight call against `https://inference.local/...\` and verify it uses `trusted_env_proxy` while preserving the hostname allowlist policy.. The changed surfaces are sandbox/runtime/infrastructure trust-boundary code (`Dockerfile`, deleted runtime verifier, and build-context staging). Existing changed tests provide useful fixture and shape coverage, but the PR removes the only test that exercised the final patched OpenClaw fetch guard module behavior.
  • PRA-T5 Acceptance clause — Reverts fix(blueprint): default OpenClaw fetch guard to sandbox proxy #5713, merged by accident — add test evidence or identify existing coverage. The diff reverts the broad Patch 4 behavior introduced by fix(blueprint): default OpenClaw fetch guard to sandbox proxy #5713 and deletes its verifier/staging, but the resulting Dockerfile is not merely deleting behavior: it restores/narrows Patch 4 to managed-proxy activation and adds Patch 6 cron preflight patching with new tests. No linked issue clauses or comments were present in the deterministic context.
  • PRA-T6 Dockerfile Patch 4 managed-proxy activation for unconfigured strict fetches — Fixture tests cover the boolean managed-proxy gate, explicit dispatcher-policy preservation, outside-sandbox behavior, and drift fail-closed behavior, but they do not import the final patched OpenClaw dist or verify actual dispatcher and SSRF behavior.. Dockerfile replaces `const canUseManagedProxy = mode === GUARDED_FETCH_MODE.STRICT && isManagedProxyActive() && hasProxyEnvConfigured();` with a condition that also accepts `process.env.OPENSHELL_SANDBOX === "1" && !params.dispatcherPolicy`.
  • PRA-T7 Dockerfile Patch 6 cron model-provider preflight trusted-env-proxy injection — New tests cover reviewed single-callsite patching, idempotence, absence, missing helper, missing policy helper, and ambiguous audit literals. They do not prove at runtime that the patched preflight call still uses the expected policy argument or that private redirects/targets remain blocked by the actual compiled fetch guard.. Dockerfile Patch 6 greps for `cron-model-provider-preflight`, requires one audit literal plus file-level `fetchWithSsrFGuard` and `buildLocalProviderSsrFPolicy`, then sed-injects `mode: "trusted_env_proxy"` before the audit context.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: cron-preflight-inference-local, network-policy, rebuild-openclaw, sandbox-rebuild, full-e2e, test-e2e-sandbox, test-e2e-gateway-isolation
Optional E2E: messaging-compatible-endpoint, common-egress-agent, sandbox-operations

Dispatch hint: cron-preflight-inference-local,network-policy,rebuild-openclaw,sandbox-rebuild,full-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • cron-preflight-inference-local (high): Directly exercises the newly added Dockerfile Patch 6 by onboarding a real sandbox and invoking OpenClaw cron model-provider preflight against the managed inference.local provider.
  • network-policy (high): Required because the PR changes fetch-guard/proxy behavior that is part of the sandbox egress security boundary and OpenShell network-policy enforcement.
  • rebuild-openclaw (high): Validates that a real OpenClaw sandbox rebuild applies the updated Dockerfile OpenClaw patch stack correctly, including stale-base upgrade and patched runtime behavior.
  • sandbox-rebuild (high): Exercises optimized sandbox build-context staging after removing verify-openclaw-fetch-guard-runtime.ts from the staged scripts and confirms a rebuilt sandbox still works.
  • full-e2e (high): The production Dockerfile and OpenClaw runtime fetch path can affect the core install/onboard/live assistant user flow, so the full hosted assistant path should be merge-blocking.
  • test-e2e-sandbox (medium): Builds and runs the sandbox test image from the changed Dockerfile, catching image-build, plugin install, blueprint, and in-container smoke regressions.
  • test-e2e-gateway-isolation (medium): Required security-boundary backstop for Dockerfile/runtime changes that alter proxy and fetch-guard behavior inside the production sandbox image.

Optional E2E

  • messaging-compatible-endpoint (medium): Adjacent confidence for inference.local routing, messaging configuration, proxy hop-header stripping, and an OpenClaw agent turn through a compatible endpoint.
  • common-egress-agent (high): Broad adjacent coverage for real onboarded sandboxes, OpenClaw agent turns, and egress policy behavior after fetch-guard/proxy changes.
  • sandbox-operations (high): Useful additional lifecycle coverage because the PR touches sandbox build context and production image behavior, but the more targeted rebuild jobs are the merge-blocking checks.

New E2E recommendations

  • OpenClaw fetch-guard runtime verification (high): The PR deletes the Dockerfile build-time runtime verifier that imported the compiled OpenClaw fetch guard and proved proxy dispatch, no local DNS, SSRF-denied literals, and private redirect rejection. Existing live jobs cover important slices but do not appear to reproduce that exact compiled-runtime contract after image patching.
    • Suggested test: Add a live or image-level E2E that runs inside the built sandbox image and imports the patched OpenClaw fetch-guard bundle to assert managed-proxy dispatch for Google certificate fetches, no local DNS for proxy-only targets, SSRF denial for private/link-local/loopback literals, and redirect revalidation.
  • Google Chat inbound webhook proxy path (medium): Patch 4 is motivated by @openclaw/googlechat JWT signing-certificate fetches, but no existing E2E job name or inspected test directly exercises a Google Chat inbound webhook/cert-fetch path through the sandbox proxy.
    • Suggested test: Add a Google Chat webhook/certificate-fetch E2E that drives the OpenClaw Google Chat inbound verification path inside a NemoClaw sandbox and confirms it reaches www.googleapis.com through the OpenShell proxy without widening SSRF policy.

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: cron-preflight-inference-local,network-policy,rebuild-openclaw,sandbox-rebuild,full-e2e

@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: ubuntu-repo-cloud-openclaw
Optional E2E targets: ubuntu-repo-cloud-langchain-deepagents-code

Dispatch required E2E targets:

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

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • ubuntu-repo-cloud-openclaw: Changes alter the sandbox Dockerfile OpenClaw fetch-guard patching and optimized sandbox build-context staging used by repo-current Docker onboarding. The Ubuntu cloud OpenClaw live target is the smallest live-supported registry target that rebuilds/onboards the sandbox image and exercises smoke, inference, and credential behavior through the changed runtime surface.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field targets=ubuntu-repo-cloud-openclaw

Optional E2E targets

  • ubuntu-repo-cloud-langchain-deepagents-code: Optional adjacent Docker/onboarding coverage on the other live-supported cloud onboarding path, useful if reviewers want confidence that the Dockerfile/build-context changes do not regress non-OpenClaw LangChain Deep Agents Code sandbox setup.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field targets=ubuntu-repo-cloud-langchain-deepagents-code

Relevant changed files

  • Dockerfile
  • scripts/verify-openclaw-fetch-guard-runtime.ts
  • src/lib/sandbox/build-context.ts

@cv
cv enabled auto-merge (squash) June 30, 2026 09:01
@cv
cv merged commit 79d9cbe into main Jun 30, 2026
54 of 56 checks passed
@cv
cv deleted the revert-5713-fix/openclaw-fetch-guard-default-proxy branch June 30, 2026 09:01

@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 `@Dockerfile`:
- Around line 430-437: Patch 6 currently rewrites the audited options by only
checking for the inserted literal, which can silently allow duplicate mode keys
if the upstream object already has one. Update the Patch 6 logic in the
Dockerfile to fail closed when the reviewed call shape already contains a mode
entry, or restrict the sed rewrite to an exact object shape so it cannot produce
conflicting keys. Add a negative-path check around the
cron-model-provider-preflight flow to prove pre-existing mode values are
rejected before applying the rewrite.
🪄 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: b637bf0e-8b0b-4d62-8962-5a0b65818ee6

📥 Commits

Reviewing files that changed from the base of the PR and between c17616f and 7119b6f.

📒 Files selected for processing (5)
  • Dockerfile
  • scripts/verify-openclaw-fetch-guard-runtime.ts
  • src/lib/sandbox/build-context.ts
  • test/fetch-guard-patch-regression.test.ts
  • test/sandbox-build-context.test.ts
💤 Files with no reviewable changes (3)
  • scripts/verify-openclaw-fetch-guard-runtime.ts
  • test/sandbox-build-context.test.ts
  • src/lib/sandbox/build-context.ts

Comment thread Dockerfile
Comment on lines +430 to +437
patched_count="$(grep -Fc 'mode: "trusted_env_proxy", auditContext: "cron-model-provider-preflight"' "$f" || true)"; \
if [ "${patched_count:-0}" -eq 1 ]; then \
echo "INFO: Patch 6 already present in $f"; \
elif [ "${patched_count:-0}" -eq 0 ]; then \
sed -i -E 's|auditContext: "cron-model-provider-preflight"|mode: "trusted_env_proxy", auditContext: "cron-model-provider-preflight"|g' "$f"; \
new_patched_count="$(grep -Fc 'mode: "trusted_env_proxy", auditContext: "cron-model-provider-preflight"' "$f" || true)"; \
[ "${new_patched_count:-0}" -eq 1 ] \
|| patch_fail "Patch 6 verification: expected exactly one patched literal in $f, found ${new_patched_count}"; \

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject pre-existing mode values before Patch 6 rewrites.

Patch 6 verifies only that the inserted literal appears once. If upstream adds a later mode key in the same audited options object, this sed rewrite can create duplicate keys and the later value will win, so the build passes while cron preflight still uses the wrong dispatcher. Add a fail-closed gate/test for an existing mode in the reviewed call shape, or rewrite only an exact reviewed object shape. As per path instructions, Dockerfile* changes must “Preserve deny-by-default behavior” and “Require negative-path tests that prove the boundary rejects bypasses.”

🤖 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 430 - 437, Patch 6 currently rewrites the audited
options by only checking for the inserted literal, which can silently allow
duplicate mode keys if the upstream object already has one. Update the Patch 6
logic in the Dockerfile to fail closed when the reviewed call shape already
contains a mode entry, or restrict the sed rewrite to an exact object shape so
it cannot produce conflicting keys. Add a negative-path check around the
cron-model-provider-preflight flow to prove pre-existing mode values are
rejected before applying the rewrite.

Source: Path instructions

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-1: Build-time runtime fetch-guard verifier removed — no test exercises actual proxy dispatch/SSRF blocking; then add or justify PRA-T1.
Open items: 1 required · 3 warnings · 3 suggestions · 7 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 6 new items found

Action checklist

  • PRA-1 Fix: Build-time runtime fetch-guard verifier removed — no test exercises actual proxy dispatch/SSRF blocking in Dockerfile:360
  • PRA-2 Resolve or justify: Patch 4 narrower than old Patch 4 — non-STRICT bare fetches may bypass sandbox proxy in Dockerfile:360
  • PRA-3 Resolve or justify: Patch 6 sed replacement fragile to OpenClaw formatting changes — fail-closed but build breaks in Dockerfile:430
  • PRA-4 Resolve or justify: Overlapping PR chore(openclaw): upgrade to 2026.6.10 and harden runtime integration #5595 (OpenClaw 2026.6.9 upgrade) may expect deleted verifier or old Patch 4 logic in Dockerfile:15
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: Patch 4 test only verifies boolean gate, not actual dispatcher selection
  • PRA-T7 Add or justify test follow-up: Acceptance clause
  • PRA-5 In-scope improvement: Patch 4 test only verifies boolean gate, not actual dispatcher selection in test/fetch-guard-patch-regression.test.ts:1095
  • PRA-6 In-scope improvement: Patch 6 removal condition not tracked — no version floor or automated reminder in Dockerfile:430
  • PRA-7 In-scope improvement: Complex inline sed for Patch 4 could be extracted to script for maintainability in Dockerfile:372

Findings index

ID Severity Category Location Required action
PRA-1 Required security Dockerfile:360 Add a build-time or CI integration test that: (1) configures a test HTTP proxy, (2) sets OPENSHELL_SANDBOX=1, (3) imports the patched fetch guard module, (4) calls fetchWithSsrFGuard with real URLs, and verifies: (a) external HTTPS fetch succeeds via proxy (dispatcher.constructor.name === 'EnvHttpProxyAgent'), (b) localhost/private IP fetches blocked before DNS (fetchCalls=0, lookupCalls=0), (c) redirect to 169.254.169.254 blocked. Alternatively, restore the runtime verifier as a build step.
PRA-2 Resolve/justify security Dockerfile:360 Audit all fetchWithSsrFGuard callsites in OpenClaw 2026.5.27 dist for non-STRICT modes without dispatcherPolicy in sandbox-sensitive contexts (Google Chat cert, cron preflight, webhook verification, etc.). Add a test fixture exercising a non-STRICT bare fetch (e.g., mode:'direct' without dispatcherPolicy) to verify it fails closed or document why the gap is acceptable.
PRA-3 Resolve/justify security Dockerfile:430 No immediate action required — fail-closed design is correct. Monitor OpenClaw releases for native mode:'trusted_env_proxy' at the callsite to remove this patch. Consider making the sed more robust (e.g., match across whitespace) if build breakage occurs.
PRA-4 Resolve/justify correctness Dockerfile:15 Coordinate with PR #5595 author. Ensure PR #5595: (1) removes any dependency on verify-openclaw-fetch-guard-runtime.ts, (2) updates its patch classifier for the new managed-proxy gate (Patch 4) and Patch 6, (3) updates integrity hashes for OpenClaw 2026.6.9.
PRA-5 Improvement tests test/fetch-guard-patch-regression.test.ts:1095 Add an integration-style fixture that imports the patched fetch-guard module (after running the Dockerfile patch block) and calls fetchWithSsrFGuard with a test URL, checking dispatcher.constructor.name === 'EnvHttpProxyAgent' for sandbox + no dispatcherPolicy, and 'PinnedDispatcher' (or equivalent) for non-sandbox or explicit dispatcherPolicy.
PRA-6 Improvement architecture Dockerfile:430 Add a build arg like PATCH_6_REMOVAL_VERSION=2026.6.0 (or next expected version) and a test that warns/fails when OPENCLAW_VERSION >= PATCH_6_REMOVAL_VERSION but Patch 6 is still applied. Or add a comment in the OPENCLAW_VERSION ARG line referencing Patch 6 removal.
PRA-7 Improvement architecture Dockerfile:372 Extract Patch 4 (and other complex patches) to a dedicated script file (e.g., scripts/patch-openclaw-fetch-guard-managed-proxy.js) that uses proper JS parsing (e.g., babel parser or simple string replacement with better readability). Keep the simple sed-based patches (Patch 1, 2, 2b, 3, 5) inline as they are straightforward.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-1 Required — Build-time runtime fetch-guard verifier removed — no test exercises actual proxy dispatch/SSRF blocking

  • Location: Dockerfile:360
  • Category: security
  • Problem: The deleted verify-openclaw-fetch-guard-runtime.ts exercised the patched fetch guard with real proxy configuration: Google Chat cert fetch via proxy without local DNS, SSRF targets (localhost, private IPs, link-local, unique-local) blocked before fetch/DNS, redirects to metadata endpoint blocked. Current unit tests mock fetchImpl/lookupFn — they verify patch application and boolean logic but NOT the undici dispatcher chain (EnvHttpProxyAgent vs pinned DNS dispatcher, redirect handling).
  • Impact: Regression in SSRF protection assurance: a patch could apply correctly (passing unit tests) but the actual runtime dispatcher chain could still route traffic incorrectly (e.g., pinned DNS instead of proxy, or redirect bypass).
  • Required action: Add a build-time or CI integration test that: (1) configures a test HTTP proxy, (2) sets OPENSHELL_SANDBOX=1, (3) imports the patched fetch guard module, (4) calls fetchWithSsrFGuard with real URLs, and verifies: (a) external HTTPS fetch succeeds via proxy (dispatcher.constructor.name === 'EnvHttpProxyAgent'), (b) localhost/private IP fetches blocked before DNS (fetchCalls=0, lookupCalls=0), (c) redirect to 169.254.169.254 blocked. Alternatively, restore the runtime verifier as a build step.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check if any existing test makes real HTTP calls through patched fetch guard: grep -r 'OPENSHELL_SANDBOX.*1' test/ --include='*.ts' | grep -v mock | grep fetchWithSsrFGuard
  • Missing regression test: Add integration test in test/fetch-guard-patch-regression.test.ts or new file that spins up a test proxy (e.g., http-proxy-middleware on localhost:3129), sets OPENSHELL_SANDBOX=1, HTTP_PROXY=http://localhost:3129, and verifies the three runtime behaviors listed above
  • Done when: The required change is committed and verification passes: Check if any existing test makes real HTTP calls through patched fetch guard: grep -r 'OPENSHELL_SANDBOX.*1' test/ --include='*.ts' | grep -v mock | grep fetchWithSsrFGuard.
  • Evidence: scripts/verify-openclaw-fetch-guard-runtime.ts deleted (was 240 lines); Dockerfile no longer runs node /usr/local/lib/nemoclaw/verify-openclaw-fetch-guard-runtime.mjs; test/fetch-guard-patch-regression.test.ts only mocks fetchImpl/lookupFn
Review findings by urgency: 1 required fix, 3 items to resolve/justify, 3 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-2 Resolve/justify — Patch 4 narrower than old Patch 4 — non-STRICT bare fetches may bypass sandbox proxy

  • Location: Dockerfile:360
  • Category: security
  • Problem: Old Patch 4 (reverted) defaulted ALL bare fetchWithSsrFGuard calls (omitted mode) to TRUSTED_ENV_PROXY in sandbox. New Patch 4 only activates managed-proxy path for STRICT mode fetches with no explicit dispatcherPolicy. Callsites explicitly passing mode:'direct' or mode:'explicit-proxy' without dispatcherPolicy would use original behavior (pinned DNS / direct connect) and fail in proxy-only sandbox netns. No audit of OpenClaw 2026.5.27 callsites for this pattern has been documented.
  • Impact: Sandbox-sensitive fetches that explicitly opt into non-STRICT modes without dispatcherPolicy would bypass the proxy, causing DNS resolution failures (EAI_AGAIN for inference.local) or direct connection attempts that fail in the proxy-only netns.
  • Recommended action: Audit all fetchWithSsrFGuard callsites in OpenClaw 2026.5.27 dist for non-STRICT modes without dispatcherPolicy in sandbox-sensitive contexts (Google Chat cert, cron preflight, webhook verification, etc.). Add a test fixture exercising a non-STRICT bare fetch (e.g., mode:'direct' without dispatcherPolicy) to verify it fails closed or document why the gap is acceptable.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run in OpenClaw 2026.5.27 dist: grep -R 'fetchWithSsrFGuard' /usr/local/lib/node_modules/openclaw/dist --include='*.js' | grep -v 'mode:' | grep -v 'dispatcherPolicy' | head -20
  • Missing regression test: Add test fixture in test/fetch-guard-patch-regression.test.ts: create a fetchWithSsrFGuard call with mode:'direct' (or 'explicit-proxy') but no dispatcherPolicy, run in sandbox (OPENSHELL_SANDBOX=1), verify behavior — either it takes managed-proxy path (if intended) or fails with clear error (if gap is acceptable)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run in OpenClaw 2026.5.27 dist: grep -R 'fetchWithSsrFGuard' /usr/local/lib/node_modules/openclaw/dist --include='*.js' | grep -v 'mode:' | grep -v 'dispatcherPolicy' | head -20.
  • Evidence: Dockerfile lines 357-387: new Patch 4 only modifies canUseManagedProxy gate for STRICT && !dispatcherPolicy; test at line 1095 only tests computeCanUseManagedProxy boolean, not downstream dispatcher selection

PRA-3 Resolve/justify — Patch 6 sed replacement fragile to OpenClaw formatting changes — fail-closed but build breaks

  • Location: Dockerfile:430
  • Category: security
  • Problem: Patch 6 uses sed -i -E 's|auditContext: "cron-model-provider-preflight"|mode: "trusted_env_proxy", auditContext: "cron-model-provider-preflight"|g' to inject the mode parameter. If OpenClaw reformats the call (multi-line, different quote style, trailing comma), the sed misses it and the build fails closed (safe but noisy). The shape gates (exactly one auditContext literal, fetchWithSsrFGuard and buildLocalProviderSsrFPolicy co-located) are strong.
  • Impact: OpenClaw minor version upgrade that reformats the preflight call (without changing semantics) would cause NemoClaw image build to fail, requiring manual patch update.
  • Recommended action: No immediate action required — fail-closed design is correct. Monitor OpenClaw releases for native mode:'trusted_env_proxy' at the callsite to remove this patch. Consider making the sed more robust (e.g., match across whitespace) if build breakage occurs.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Verify current OpenClaw 2026.5.27 dist matches sed pattern: grep -n 'auditContext: "cron-model-provider-preflight"' /usr/local/lib/node_modules/openclaw/dist/*.js
  • Missing regression test: Existing tests cover: 'applies Patch 6 to a reviewed single-callsite cron preflight fixture' (happy path), 'treats an already-patched cron preflight fixture as a no-op' (idempotent), 'fails Patch 6 closed when the audit context literal is ambiguous (multi-callsite)' (guard). No test for formatting variations — consider adding one if OpenClaw formatting is unstable.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Verify current OpenClaw 2026.5.27 dist matches sed pattern: grep -n 'auditContext: "cron-model-provider-preflight"' /usr/local/lib/node_modules/openclaw/dist/*.js.
  • Evidence: Dockerfile lines 391-444 (Patch 6); test/fetch-guard-patch-regression.test.ts lines 1273-1339 (5 tests for Patch 6)

PRA-4 Resolve/justify — Overlapping PR #5595 (OpenClaw 2026.6.9 upgrade) may expect deleted verifier or old Patch 4 logic

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-5 Improvement — Patch 4 test only verifies boolean gate, not actual dispatcher selection

  • Location: test/fetch-guard-patch-regression.test.ts:1095
  • Category: tests
  • Problem: Test 'activates the managed-proxy path for unconfigured strict fetches only inside the sandbox' mocks isManagedProxyActive/hasProxyEnvConfigured and checks computeCanUseManagedProxy returns true/false. It does NOT verify that when canUseManagedProxy=true, fetchWithSsrFGuard actually uses EnvHttpProxyAgent (env proxy) vs the pinned DNS dispatcher.
  • Impact: Patch could pass boolean gate test but the downstream dispatcher selection in fetchWithSsrFGuard could still be wrong (e.g., not checking canUseManagedProxy before creating dispatcher).
  • Suggested action: Add an integration-style fixture that imports the patched fetch-guard module (after running the Dockerfile patch block) and calls fetchWithSsrFGuard with a test URL, checking dispatcher.constructor.name === 'EnvHttpProxyAgent' for sandbox + no dispatcherPolicy, and 'PinnedDispatcher' (or equivalent) for non-sandbox or explicit dispatcherPolicy.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Review test at line 1095 — it exports computeCanUseManagedProxy as 'g' and tests g('strict', {}) boolean return; no import of fetchWithSsrFGuard or dispatcher inspection
  • Missing regression test: Add test case in same test block: after patching, import fetchWithSsrFGuard from the patched module, call with { url: 'https://example.com', mode: 'strict' } in sandbox, assert dispatcher.constructor.name includes 'EnvHttpProxyAgent' or 'ProxyAgent'
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: test/fetch-guard-patch-regression.test.ts lines 1095-1153

PRA-6 Improvement — Patch 6 removal condition not tracked — no version floor or automated reminder

  • Location: Dockerfile:430
  • Category: architecture
  • Problem: Patch 6 comment documents removal condition: 'drop once an OpenClaw release sets mode: trusted_env_proxy directly at the preflight call site or otherwise routes the managed inference base URL through the env-proxy dispatcher by default.' No build arg, version check, or test exists to remind maintainers to revisit when OPENCLAW_VERSION is bumped.
  • Impact: Patch 6 may persist after upstream fix, adding unnecessary build complexity and potential for drift.
  • Suggested action: Add a build arg like PATCH_6_REMOVAL_VERSION=2026.6.0 (or next expected version) and a test that warns/fails when OPENCLAW_VERSION >= PATCH_6_REMOVAL_VERSION but Patch 6 is still applied. Or add a comment in the OPENCLAW_VERSION ARG line referencing Patch 6 removal.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check if any automated mechanism tracks patch removal: grep -r 'REMOVAL_VERSION\|removal.*version' Dockerfile Dockerfile.base
  • Missing regression test: N/A — maintenance tracking; could add test 'fails when Patch 6 applied but OpenClaw version exceeds removal threshold'
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Dockerfile line 430 comment; OPENCLAW_VERSION=2026.5.27 at line 15

PRA-7 Improvement — Complex inline sed for Patch 4 could be extracted to script for maintainability

  • Location: Dockerfile:372
  • Category: architecture
  • Problem: The sed command at line 372 is a complex regex with escaped ampersands, parentheses, and semicolons. It modifies a single line but the pattern is hard to read and verify. The verification grep at line 373 duplicates the pattern.
  • Impact: Harder to audit, update, and debug when OpenClaw dist shape changes. Increases risk of regex mismatch causing silent patch failure or build failure.
  • Suggested action: Extract Patch 4 (and other complex patches) to a dedicated script file (e.g., scripts/patch-openclaw-fetch-guard-managed-proxy.js) that uses proper JS parsing (e.g., babel parser or simple string replacement with better readability). Keep the simple sed-based patches (Patch 1, 2, 2b, 3, 5) inline as they are straightforward.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare readability: Dockerfile line 372 sed vs scripts/patch-openclaw-tool-catalog.js (separate script)
  • Missing regression test: N/A — refactor only; existing tests would verify behavior unchanged
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Dockerfile line 372: sed -i -E 's#const canUseManagedProxy = mode === GUARDED_FETCH_MODE\.STRICT \&\& isManagedProxyActive\(\) \&\& hasProxyEnvConfigured\(\);#const canUseManagedProxy = mode === GUARDED_FETCH_MODE.STRICT \&\& (isManagedProxyActive() || (process.env.OPENSHELL_SANDBOX === "1" \&\& !params.dispatcherPolicy)) \&\& hasProxyEnvConfigured(); /* nemoclaw: route unconfigured strict fetch through sandbox egress proxy, see Dockerfile */#'
Simplification opportunities: 1 possible cut

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-7 shrink (Dockerfile:372): Inline sed command at Dockerfile line 372 (and similar complex patches)
    • Replacement: Extract to scripts/patch-openclaw-fetch-guard-managed-proxy.js with proper string replacement or AST transform
    • Net: 10 lines
    • Safety boundary: Must preserve exact same patch logic, verification grep, and fail-closed behavior; tests in fetch-guard-patch-regression.test.ts must pass unchanged
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — fetchWithSsrFGuard with mode:strict + no dispatcherPolicy in sandbox uses EnvHttpProxyAgent (integration fixture with test proxy). Changed files are Dockerfile (build-time patching), build-context (staging), and security-critical SSRF patches. Unit tests verify patch application and some logic but don't exercise the actual undici dispatcher chain. The deleted runtime verifier provided end-to-end validation of proxy dispatch, SSRF blocks, and redirect checks.
  • PRA-T2 Runtime validation — fetchWithSsrFGuard with mode:direct + no dispatcherPolicy in sandbox — verify fail or document gap (covers F1). Changed files are Dockerfile (build-time patching), build-context (staging), and security-critical SSRF patches. Unit tests verify patch application and some logic but don't exercise the actual undici dispatcher chain. The deleted runtime verifier provided end-to-end validation of proxy dispatch, SSRF blocks, and redirect checks.
  • PRA-T3 Runtime validation — redirect to 169.254.169.254 blocked after patch (was in deleted verifier). Changed files are Dockerfile (build-time patching), build-context (staging), and security-critical SSRF patches. Unit tests verify patch application and some logic but don't exercise the actual undici dispatcher chain. The deleted runtime verifier provided end-to-end validation of proxy dispatch, SSRF blocks, and redirect checks.
  • PRA-T4 Runtime validation — Google Chat cert fetch succeeds via proxy without local DNS in sandbox (was in deleted verifier). Changed files are Dockerfile (build-time patching), build-context (staging), and security-critical SSRF patches. Unit tests verify patch application and some logic but don't exercise the actual undici dispatcher chain. The deleted runtime verifier provided end-to-end validation of proxy dispatch, SSRF blocks, and redirect checks.
  • PRA-T5 Runtime validation — Patch 6 formatting robustness: multi-line auditContext, different quote styles (if OpenClaw formatting is unstable). Changed files are Dockerfile (build-time patching), build-context (staging), and security-critical SSRF patches. Unit tests verify patch application and some logic but don't exercise the actual undici dispatcher chain. The deleted runtime verifier provided end-to-end validation of proxy dispatch, SSRF blocks, and redirect checks.
  • PRA-T6 Patch 4 test only verifies boolean gate, not actual dispatcher selection — Add an integration-style fixture that imports the patched fetch-guard module (after running the Dockerfile patch block) and calls fetchWithSsrFGuard with a test URL, checking dispatcher.constructor.name === 'EnvHttpProxyAgent' for sandbox + no dispatcherPolicy, and 'PinnedDispatcher' (or equivalent) for non-sandbox or explicit dispatcherPolicy.
  • PRA-T7 Acceptance clause — Tracking issue for replacement design — add test evidence or identify existing coverage. PR body only cites historical issues (@openclaw/googlechat cert fetch fails: SSRF guard's per-request dispatcher bypasses NemoClaw's nemoclaw-http-proxy-fix.js global-agent hook #4687, NemoClaw sandbox: Gemini web_search fails with EAI_AGAIN until Google host + node are allowed, and trusted proxy still does local DNS lookup #396, fix(sandbox): cron preflight inference.local uses trusted env-proxy mode #5129); no linked issue for this specific replacement design
Since last review details

Current findings, using the urgency labels above:

PRA-1 Required — Build-time runtime fetch-guard verifier removed — no test exercises actual proxy dispatch/SSRF blocking

  • Location: Dockerfile:360
  • Category: security
  • Problem: The deleted verify-openclaw-fetch-guard-runtime.ts exercised the patched fetch guard with real proxy configuration: Google Chat cert fetch via proxy without local DNS, SSRF targets (localhost, private IPs, link-local, unique-local) blocked before fetch/DNS, redirects to metadata endpoint blocked. Current unit tests mock fetchImpl/lookupFn — they verify patch application and boolean logic but NOT the undici dispatcher chain (EnvHttpProxyAgent vs pinned DNS dispatcher, redirect handling).
  • Impact: Regression in SSRF protection assurance: a patch could apply correctly (passing unit tests) but the actual runtime dispatcher chain could still route traffic incorrectly (e.g., pinned DNS instead of proxy, or redirect bypass).
  • Required action: Add a build-time or CI integration test that: (1) configures a test HTTP proxy, (2) sets OPENSHELL_SANDBOX=1, (3) imports the patched fetch guard module, (4) calls fetchWithSsrFGuard with real URLs, and verifies: (a) external HTTPS fetch succeeds via proxy (dispatcher.constructor.name === 'EnvHttpProxyAgent'), (b) localhost/private IP fetches blocked before DNS (fetchCalls=0, lookupCalls=0), (c) redirect to 169.254.169.254 blocked. Alternatively, restore the runtime verifier as a build step.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check if any existing test makes real HTTP calls through patched fetch guard: grep -r 'OPENSHELL_SANDBOX.*1' test/ --include='*.ts' | grep -v mock | grep fetchWithSsrFGuard
  • Missing regression test: Add integration test in test/fetch-guard-patch-regression.test.ts or new file that spins up a test proxy (e.g., http-proxy-middleware on localhost:3129), sets OPENSHELL_SANDBOX=1, HTTP_PROXY=http://localhost:3129, and verifies the three runtime behaviors listed above
  • Done when: The required change is committed and verification passes: Check if any existing test makes real HTTP calls through patched fetch guard: grep -r 'OPENSHELL_SANDBOX.*1' test/ --include='*.ts' | grep -v mock | grep fetchWithSsrFGuard.
  • Evidence: scripts/verify-openclaw-fetch-guard-runtime.ts deleted (was 240 lines); Dockerfile no longer runs node /usr/local/lib/nemoclaw/verify-openclaw-fetch-guard-runtime.mjs; test/fetch-guard-patch-regression.test.ts only mocks fetchImpl/lookupFn

PRA-2 Resolve/justify — Patch 4 narrower than old Patch 4 — non-STRICT bare fetches may bypass sandbox proxy

  • Location: Dockerfile:360
  • Category: security
  • Problem: Old Patch 4 (reverted) defaulted ALL bare fetchWithSsrFGuard calls (omitted mode) to TRUSTED_ENV_PROXY in sandbox. New Patch 4 only activates managed-proxy path for STRICT mode fetches with no explicit dispatcherPolicy. Callsites explicitly passing mode:'direct' or mode:'explicit-proxy' without dispatcherPolicy would use original behavior (pinned DNS / direct connect) and fail in proxy-only sandbox netns. No audit of OpenClaw 2026.5.27 callsites for this pattern has been documented.
  • Impact: Sandbox-sensitive fetches that explicitly opt into non-STRICT modes without dispatcherPolicy would bypass the proxy, causing DNS resolution failures (EAI_AGAIN for inference.local) or direct connection attempts that fail in the proxy-only netns.
  • Recommended action: Audit all fetchWithSsrFGuard callsites in OpenClaw 2026.5.27 dist for non-STRICT modes without dispatcherPolicy in sandbox-sensitive contexts (Google Chat cert, cron preflight, webhook verification, etc.). Add a test fixture exercising a non-STRICT bare fetch (e.g., mode:'direct' without dispatcherPolicy) to verify it fails closed or document why the gap is acceptable.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run in OpenClaw 2026.5.27 dist: grep -R 'fetchWithSsrFGuard' /usr/local/lib/node_modules/openclaw/dist --include='*.js' | grep -v 'mode:' | grep -v 'dispatcherPolicy' | head -20
  • Missing regression test: Add test fixture in test/fetch-guard-patch-regression.test.ts: create a fetchWithSsrFGuard call with mode:'direct' (or 'explicit-proxy') but no dispatcherPolicy, run in sandbox (OPENSHELL_SANDBOX=1), verify behavior — either it takes managed-proxy path (if intended) or fails with clear error (if gap is acceptable)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run in OpenClaw 2026.5.27 dist: grep -R 'fetchWithSsrFGuard' /usr/local/lib/node_modules/openclaw/dist --include='*.js' | grep -v 'mode:' | grep -v 'dispatcherPolicy' | head -20.
  • Evidence: Dockerfile lines 357-387: new Patch 4 only modifies canUseManagedProxy gate for STRICT && !dispatcherPolicy; test at line 1095 only tests computeCanUseManagedProxy boolean, not downstream dispatcher selection

PRA-3 Resolve/justify — Patch 6 sed replacement fragile to OpenClaw formatting changes — fail-closed but build breaks

  • Location: Dockerfile:430
  • Category: security
  • Problem: Patch 6 uses sed -i -E 's|auditContext: "cron-model-provider-preflight"|mode: "trusted_env_proxy", auditContext: "cron-model-provider-preflight"|g' to inject the mode parameter. If OpenClaw reformats the call (multi-line, different quote style, trailing comma), the sed misses it and the build fails closed (safe but noisy). The shape gates (exactly one auditContext literal, fetchWithSsrFGuard and buildLocalProviderSsrFPolicy co-located) are strong.
  • Impact: OpenClaw minor version upgrade that reformats the preflight call (without changing semantics) would cause NemoClaw image build to fail, requiring manual patch update.
  • Recommended action: No immediate action required — fail-closed design is correct. Monitor OpenClaw releases for native mode:'trusted_env_proxy' at the callsite to remove this patch. Consider making the sed more robust (e.g., match across whitespace) if build breakage occurs.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Verify current OpenClaw 2026.5.27 dist matches sed pattern: grep -n 'auditContext: "cron-model-provider-preflight"' /usr/local/lib/node_modules/openclaw/dist/*.js
  • Missing regression test: Existing tests cover: 'applies Patch 6 to a reviewed single-callsite cron preflight fixture' (happy path), 'treats an already-patched cron preflight fixture as a no-op' (idempotent), 'fails Patch 6 closed when the audit context literal is ambiguous (multi-callsite)' (guard). No test for formatting variations — consider adding one if OpenClaw formatting is unstable.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Verify current OpenClaw 2026.5.27 dist matches sed pattern: grep -n 'auditContext: "cron-model-provider-preflight"' /usr/local/lib/node_modules/openclaw/dist/*.js.
  • Evidence: Dockerfile lines 391-444 (Patch 6); test/fetch-guard-patch-regression.test.ts lines 1273-1339 (5 tests for Patch 6)

PRA-4 Resolve/justify — Overlapping PR #5595 (OpenClaw 2026.6.9 upgrade) may expect deleted verifier or old Patch 4 logic

PRA-5 Improvement — Patch 4 test only verifies boolean gate, not actual dispatcher selection

  • Location: test/fetch-guard-patch-regression.test.ts:1095
  • Category: tests
  • Problem: Test 'activates the managed-proxy path for unconfigured strict fetches only inside the sandbox' mocks isManagedProxyActive/hasProxyEnvConfigured and checks computeCanUseManagedProxy returns true/false. It does NOT verify that when canUseManagedProxy=true, fetchWithSsrFGuard actually uses EnvHttpProxyAgent (env proxy) vs the pinned DNS dispatcher.
  • Impact: Patch could pass boolean gate test but the downstream dispatcher selection in fetchWithSsrFGuard could still be wrong (e.g., not checking canUseManagedProxy before creating dispatcher).
  • Suggested action: Add an integration-style fixture that imports the patched fetch-guard module (after running the Dockerfile patch block) and calls fetchWithSsrFGuard with a test URL, checking dispatcher.constructor.name === 'EnvHttpProxyAgent' for sandbox + no dispatcherPolicy, and 'PinnedDispatcher' (or equivalent) for non-sandbox or explicit dispatcherPolicy.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Review test at line 1095 — it exports computeCanUseManagedProxy as 'g' and tests g('strict', {}) boolean return; no import of fetchWithSsrFGuard or dispatcher inspection
  • Missing regression test: Add test case in same test block: after patching, import fetchWithSsrFGuard from the patched module, call with { url: 'https://example.com', mode: 'strict' } in sandbox, assert dispatcher.constructor.name includes 'EnvHttpProxyAgent' or 'ProxyAgent'
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: test/fetch-guard-patch-regression.test.ts lines 1095-1153

PRA-6 Improvement — Patch 6 removal condition not tracked — no version floor or automated reminder

  • Location: Dockerfile:430
  • Category: architecture
  • Problem: Patch 6 comment documents removal condition: 'drop once an OpenClaw release sets mode: trusted_env_proxy directly at the preflight call site or otherwise routes the managed inference base URL through the env-proxy dispatcher by default.' No build arg, version check, or test exists to remind maintainers to revisit when OPENCLAW_VERSION is bumped.
  • Impact: Patch 6 may persist after upstream fix, adding unnecessary build complexity and potential for drift.
  • Suggested action: Add a build arg like PATCH_6_REMOVAL_VERSION=2026.6.0 (or next expected version) and a test that warns/fails when OPENCLAW_VERSION >= PATCH_6_REMOVAL_VERSION but Patch 6 is still applied. Or add a comment in the OPENCLAW_VERSION ARG line referencing Patch 6 removal.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check if any automated mechanism tracks patch removal: grep -r 'REMOVAL_VERSION\|removal.*version' Dockerfile Dockerfile.base
  • Missing regression test: N/A — maintenance tracking; could add test 'fails when Patch 6 applied but OpenClaw version exceeds removal threshold'
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Dockerfile line 430 comment; OPENCLAW_VERSION=2026.5.27 at line 15

PRA-7 Improvement — Complex inline sed for Patch 4 could be extracted to script for maintainability

  • Location: Dockerfile:372
  • Category: architecture
  • Problem: The sed command at line 372 is a complex regex with escaped ampersands, parentheses, and semicolons. It modifies a single line but the pattern is hard to read and verify. The verification grep at line 373 duplicates the pattern.
  • Impact: Harder to audit, update, and debug when OpenClaw dist shape changes. Increases risk of regex mismatch causing silent patch failure or build failure.
  • Suggested action: Extract Patch 4 (and other complex patches) to a dedicated script file (e.g., scripts/patch-openclaw-fetch-guard-managed-proxy.js) that uses proper JS parsing (e.g., babel parser or simple string replacement with better readability). Keep the simple sed-based patches (Patch 1, 2, 2b, 3, 5) inline as they are straightforward.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare readability: Dockerfile line 372 sed vs scripts/patch-openclaw-tool-catalog.js (separate script)
  • Missing regression test: N/A — refactor only; existing tests would verify behavior unchanged
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Dockerfile line 372: sed -i -E 's#const canUseManagedProxy = mode === GUARDED_FETCH_MODE\.STRICT \&\& isManagedProxyActive\(\) \&\& hasProxyEnvConfigured\(\);#const canUseManagedProxy = mode === GUARDED_FETCH_MODE.STRICT \&\& (isManagedProxyActive() || (process.env.OPENSHELL_SANDBOX === "1" \&\& !params.dispatcherPolicy)) \&\& hasProxyEnvConfigured(); /* nemoclaw: route unconfigured strict fetch through sandbox egress proxy, see Dockerfile */#'

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…proxy (NVIDIA#6051)

Reverts NVIDIA#5713, merged by accident

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved sandbox proxy handling so unconfigured strict network
requests are routed correctly in OpenShell environments.
* Added safer cron preflight behavior to avoid breaking DNS-pinned
strict-mode runs in proxy-only sandboxes.

* **Chores**
* Removed an unused runtime verification step and simplified the build
process.
* Updated related automation and test coverage to match the new proxy
and patching behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Carlos Villela <cv@lixo.org>
@wscurran wscurran added bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants