Skip to content

Dockerfile: bump OpenClaw to 2026.3.22, widen CORS and trusted proxies#740

Open
cluster2600 wants to merge 1 commit intoNVIDIA:mainfrom
cluster2600:fix/openclaw-2026.3.22-and-cors
Open

Dockerfile: bump OpenClaw to 2026.3.22, widen CORS and trusted proxies#740
cluster2600 wants to merge 1 commit intoNVIDIA:mainfrom
cluster2600:fix/openclaw-2026.3.22-and-cors

Conversation

@cluster2600
Copy link

@cluster2600 cluster2600 commented Mar 23, 2026

Summary

  • Bump OpenClaw from 2026.3.11 to 2026.3.22 — picks up recent fixes
  • Widen allowedOrigins — add '*' and http://127.0.0.1:3333 so that remote dashboard access (Mission Control, SSH tunnels from LAN machines) works without manual config changes. The sandbox config is read-only at runtime, so users currently have no way to fix this themselves without rebuilding the image.
  • Add RFC 1918 CIDRs to trustedProxies10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 so that X-Forwarded-For headers are trusted correctly in reverse proxy and SSH tunnel setups, which are the standard access pattern for headless DGX Spark deployments.

Motivation

On a headless DGX Spark accessed via SSH tunnel or LAN, the current config blocks legitimate dashboard connections because:

  1. allowedOrigins only includes http://127.0.0.1:18789
  2. trustedProxies only includes loopback addresses

Since openclaw.json is intentionally immutable in the sandbox (Landlock + DAC), users cannot fix this at runtime — it must be correct at image build time.

Fixes #739

Test plan

  • Build the sandbox image with the updated Dockerfile
  • Verify OpenClaw 2026.3.22 is installed: openclaw --version
  • Access Mission Control from a remote machine via SSH tunnel on port 3333
  • Confirm gateway accepts requests from LAN origin through reverse proxy

Summary by CodeRabbit

  • Chores
    • Updated OpenClaw CLI to version 2026.3.22.
    • Enhanced network and CORS configuration to support broader access patterns and additional private network ranges for improved multi-environment deployment compatibility.

- Update openclaw from 2026.3.11 to 2026.3.22
- Add wildcard and port 3333 to allowedOrigins so remote dashboard
  access (Mission Control, SSH tunnels) works out of the box
- Add RFC 1918 private network CIDRs to trustedProxies for reverse
  proxy and SSH tunnel setups common on headless DGX Spark deployments

Fixes: NVIDIA#739
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

The Dockerfile updates the OpenClaw CLI version from 2026.3.11 to 2026.3.22 and modifies the generated openclaw.json configuration to expand network access permissions by broadening allowedOrigins and trustedProxies to include common remote deployment scenarios.

Changes

Cohort / File(s) Summary
Dockerfile configuration
Dockerfile
OpenClaw version bumped from 2026.3.11 to 2026.3.22; gateway.controlUi.allowedOrigins expanded from localhost-only to include wildcard and port 3333; gateway.trustedProxies expanded to include private network CIDR ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) for reverse proxy and SSH tunnel scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A faster Claw hops into view,
From 3.11 to 3.22, newer and true!
Doors swing wide with '*' and port 3333,
Private nets now trusted, no security riddle! ✨

🚥 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 changes: bumping OpenClaw version and widening CORS/trusted proxies configuration.
Linked Issues check ✅ Passed The PR addresses all three main requirements from issue #739: bumps OpenClaw to 2026.3.22, expands allowedOrigins to include '*' and 3333, and adds RFC 1918 CIDRs to trustedProxies.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the Dockerfile configuration requirements: version bump, CORS allowedOrigins expansion, and trustedProxies extension.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
Dockerfile (1)

59-60: Expose the OpenClaw version as a build arg to support rebuild-time upgrades without file edits.

The Dockerfile already uses ARGs for "config that varies per deployment" (line 82 comment). The OpenClaw version fits this pattern perfectly—it differs between the main Dockerfile (2026.3.22) and test Dockerfile (2026.3.11), and operators need a way to upgrade without editing the file.

♻️ Suggested change
+# Allows rebuild-time OpenClaw upgrades without editing this file.
+ARG OPENCLAW_VERSION=2026.3.22
+
 # Install OpenClaw CLI and PyYAML for blueprint runner (single layer)
-RUN npm install -g openclaw@2026.3.22 \
+RUN npm install -g openclaw@${OPENCLAW_VERSION} \
     && pip3 install --no-cache-dir --break-system-packages "pyyaml==6.0.3"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 59 - 60, Add a build ARG for the OpenClaw version
and use it in the npm install command so operators can override the version at
build time; introduce ARG OPENCLAW_VERSION with the current default value (e.g.,
2026.3.22) before the RUN that installs openclaw and replace the hard-coded
literal in the RUN npm install -g openclaw@... with
openclaw@${OPENCLAW_VERSION}; also update any companion test Dockerfile or build
scripts that currently rely on the hard-coded version to pass a different
--build-arg OPENCLAW_VERSION when needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Around line 109-110: The default CORS origins list currently includes the
wildcard '*' (variable origins) which permits any browser origin; remove '*'
from the hardcoded default origins and only include chat_origin (derived from
CHAT_UI_URL) and any explicitly configured opt-in origins. Update the origins
assignment (the origins variable and the subsequent list(dict.fromkeys(origins +
[chat_origin])) logic) to: 1) omit '*' from the initial list, 2) append
chat_origin if present, and 3) optionally append extra origins only when an
explicit env/config (e.g., ALLOWED_ORIGINS or a configured extra_origins value)
is provided—preserve the uniqueness dedup step and keep
dangerouslyDisableDeviceAuth and allowInsecureAuth handling unchanged.
- Line 135: The current default for 'trustedProxies' includes all RFC1918 ranges
which allows any host on those networks to supply X-Forwarded-For; change the
Dockerfile/default config so 'trustedProxies' defaults to only loopback
(['127.0.0.1', '::1']) and add a build-time argument (e.g., PROXY_CIDRS) to pass
the actual proxy IPs/CIDRs into the image, then populate 'trustedProxies' from
that arg at build/startup (if provided) so deployments explicitly supply gateway
IPs/CIDRs rather than trusting entire private ranges.

---

Nitpick comments:
In `@Dockerfile`:
- Around line 59-60: Add a build ARG for the OpenClaw version and use it in the
npm install command so operators can override the version at build time;
introduce ARG OPENCLAW_VERSION with the current default value (e.g., 2026.3.22)
before the RUN that installs openclaw and replace the hard-coded literal in the
RUN npm install -g openclaw@... with openclaw@${OPENCLAW_VERSION}; also update
any companion test Dockerfile or build scripts that currently rely on the
hard-coded version to pass a different --build-arg OPENCLAW_VERSION when needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 548d94ed-e641-4d64-a760-aed9fc92423f

📥 Commits

Reviewing files that changed from the base of the PR and between a1e7485 and 41f85f9.

📒 Files selected for processing (1)
  • Dockerfile

Comment on lines +109 to 110
origins = ['*', 'http://127.0.0.1:18789', 'http://127.0.0.1:3333']; \
origins = list(dict.fromkeys(origins + [chat_origin])); \
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does OpenClaw's gateway.controlUi.allowedOriginstreat'*'as a wildcard, and are there documented security caveats whenallowInsecureAuthanddangerouslyDisableDeviceAuth are enabled?

💡 Result:

  • Yes. gateway.controlUi.allowedOrigins: ["*"] is treated as “allow any browser origin” (i.e., a wildcard). The docs explicitly warn it does not mean “match whatever host I’m using,” and say to avoid it except for tightly controlled local testing. [1]

  • Documented security caveats:

    • gateway.controlUi.allowInsecureAuth is described as a local compatibility toggle only: it allows localhost Control UI sessions to proceed without device identity in non-secure HTTP contexts, does not bypass pairing, and does not relax remote (non-localhost) device-identity requirements. [1]
    • gateway.controlUi.dangerouslyDisableDeviceAuth disables Control UI device identity checks and is documented as a severe security downgrade (“break-glass only; revert quickly”). It is also flagged as a critical security finding in the Gateway security guidance. [1][2]

🏁 Script executed:

#!/bin/bash
# Read the Dockerfile around lines 109-110 with broader context
head -130 Dockerfile | tail -30

Repository: NVIDIA/NemoClaw

Length of output: 1625


🏁 Script executed:

#!/bin/bash
# Search for gateway config setup and flag enablement
rg -n "allowInsecureAuth|dangerouslyDisableDeviceAuth|controlUi" Dockerfile -B 2 -A 2

Repository: NVIDIA/NemoClaw

Length of output: 304


🏁 Script executed:

#!/bin/bash
# Look for any environment variable patterns and build args
rg -n "ENV|ARG" Dockerfile | head -20

Repository: NVIDIA/NemoClaw

Length of output: 349


Remove the wildcard from the default CORS origins list.

The '*' at line 109 allows any browser origin to access the Control UI (confirmed by OpenClaw docs). Combined with dangerouslyDisableDeviceAuth: True enabled at line 132, this removes device identity validation entirely—a severe security downgrade. The allowInsecureAuth flag only applies to localhost, not cross-origin requests.

chat_origin derived from CHAT_UI_URL already covers the remote dashboard case. Instead of shipping '*' as a default, make extra origins opt-in:

Suggested approach
-origins = ['*', 'http://127.0.0.1:18789', 'http://127.0.0.1:3333']; \
+extra_origins = [o.strip() for o in os.environ.get('OPENCLAW_ALLOWED_ORIGINS', '').split(',') if o.strip()]; \
+origins = ['http://127.0.0.1:18789', 'http://127.0.0.1:3333', *extra_origins]; \
 origins = list(dict.fromkeys(origins + [chat_origin])); \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
origins = ['*', 'http://127.0.0.1:18789', 'http://127.0.0.1:3333']; \
origins = list(dict.fromkeys(origins + [chat_origin])); \
extra_origins = [o.strip() for o in os.environ.get('OPENCLAW_ALLOWED_ORIGINS', '').split(',') if o.strip()]; \
origins = ['http://127.0.0.1:18789', 'http://127.0.0.1:3333', *extra_origins]; \
origins = list(dict.fromkeys(origins + [chat_origin])); \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 109 - 110, The default CORS origins list currently
includes the wildcard '*' (variable origins) which permits any browser origin;
remove '*' from the hardcoded default origins and only include chat_origin
(derived from CHAT_UI_URL) and any explicitly configured opt-in origins. Update
the origins assignment (the origins variable and the subsequent
list(dict.fromkeys(origins + [chat_origin])) logic) to: 1) omit '*' from the
initial list, 2) append chat_origin if present, and 3) optionally append extra
origins only when an explicit env/config (e.g., ALLOWED_ORIGINS or a configured
extra_origins value) is provided—preserve the uniqueness dedup step and keep
dangerouslyDisableDeviceAuth and allowInsecureAuth handling unchanged.

'allowedOrigins': origins, \
}, \
'trustedProxies': ['127.0.0.1', '::1'], \
'trustedProxies': ['127.0.0.1', '::1', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'], \
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does OpenClaw's gateway.trustedProxiesaccept CIDR ranges, and if so, does trusting all RFC1918 ranges causeX-Forwarded-For from any private-network client to be honored?

💡 Result:

Yes—gateway.trustedProxies effectively accepts CIDR ranges.

  • In OpenClaw’s gateway code, proxy trust is checked with isIpInCidr(normalized, candidate), where each candidate is an entry from trustedProxies (so entries like 10.0.0.0/8 work, not just single IPs). [1]
  • When trustedProxies is set, the Gateway uses X-Forwarded-For to determine the client IP (and ignores X-Real-IP unless explicitly enabled). [2]

And yes—if you “trust” all RFC1918 ranges (e.g., 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), then any client connecting from those private address ranges will be treated as a trusted proxy, meaning their X-Forwarded-For chain will be honored for client-IP resolution. That’s why the docs emphasize only adding your actual proxy IPs. [1][3]

Important nuance: this does not automatically make such clients “local”; OpenClaw fails closed if a request arrives from a “trusted proxy” IP but forwarded headers are missing/invalid, and it still has additional “local direct” checks beyond just trusting X-Forwarded-For. [1]

Sources:
[1] https://raw.githubusercontent.com/openclaw/openclaw/refs/heads/main/src/gateway/net.ts
[2] https://docs.openclaw.ai/gateway/security
[3] https://docs.openclaw.ai/gateway/trusted-proxy-auth


Scope trustedProxies to the real proxy hop.

Line 135 trusts all RFC 1918 ranges by default. Since CIDR ranges are honored for proxy trust checks, this means any host on those private networks can provide X-Forwarded-For headers that will be used for client IP resolution—weakening client IP attribution and IP-based controls in deployments where the gateway is reachable directly from the LAN/VPC. Default to loopback only and pass actual proxy IPs/CIDRs via a build argument.

🛡️ Suggested approach
-        'trustedProxies': ['127.0.0.1', '::1', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'], \
+        'trustedProxies': ['127.0.0.1', '::1'] + [p.strip() for p in os.environ.get('OPENCLAW_TRUSTED_PROXIES', '').split(',') if p.strip()], \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` at line 135, The current default for 'trustedProxies' includes
all RFC1918 ranges which allows any host on those networks to supply
X-Forwarded-For; change the Dockerfile/default config so 'trustedProxies'
defaults to only loopback (['127.0.0.1', '::1']) and add a build-time argument
(e.g., PROXY_CIDRS) to pass the actual proxy IPs/CIDRs into the image, then
populate 'trustedProxies' from that arg at build/startup (if provided) so
deployments explicitly supply gateway IPs/CIDRs rather than trusting entire
private ranges.

@wscurran wscurran added bug Something isn't working Docker Support for Docker containerization enhancement: feature Use this label to identify requests for new capabilities in NemoClaw. priority: medium Issue that should be addressed in upcoming releases labels Mar 24, 2026
@wscurran
Copy link
Contributor

Thanks for submitting this PR, it addresses the issue with the pinned OpenClaw version and restrictive allowedOrigins in the Dockerfile configuration, and suggests enhancements to improve the setup process and remote dashboard access.

@wscurran wscurran added the Integration: OpenClaw Support for OpenClaw label Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Docker Support for Docker containerization enhancement: feature Use this label to identify requests for new capabilities in NemoClaw. Integration: OpenClaw Support for OpenClaw priority: medium Issue that should be addressed in upcoming releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dockerfile: pinned OpenClaw version, restrictive allowedOrigins, no way to update in sandbox

2 participants