Skip to content

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

Closed
cluster2600 wants to merge 2 commits intoNVIDIA:mainfrom
cluster2600:fix/openclaw-2026.3.22-and-cors
Closed

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

Conversation

@cluster2600
Copy link
Copy Markdown
Contributor

@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
    • Broadened UI allowed origins to permit all origins while retaining existing localhost access.
    • Expanded trusted proxy list to include common private-network ranges in addition to loopback addresses for private network deployments.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5ddf7cfd-61c3-4cec-96d4-f386aaf9e5dc

📥 Commits

Reviewing files that changed from the base of the PR and between ee6f0de and 24dcad5.

📒 Files selected for processing (1)
  • Dockerfile
✅ Files skipped from review due to trivial changes (1)
  • Dockerfile

📝 Walkthrough

Walkthrough

Updated the generated openclaw.json gateway configuration: gateway.controlUi.allowedOrigins now includes '*' and http://127.0.0.1:3333 (deduped and still includes chat_origin), and gateway.trustedProxies now includes private-network CIDR ranges in addition to loopback addresses.

Changes

Cohort / File(s) Summary
Generated gateway config
openclaw.json
Expanded gateway.controlUi.allowedOrigins to include '*' and http://127.0.0.1:3333 (deduping preserved, chat_origin retained). Expanded gateway.trustedProxies from loopback-only (127.0.0.1, ::1) to also include 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibbled at a JSON line,
Allowed more doors to sun and sign.
From localhost to networks wide,
Trusted paths now stroll beside.
Hop on — the gateway's open-eyed. 🥕

🚥 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 Title accurately summarizes the main changes: OpenClaw version bump and widening CORS/trusted proxies configuration, matching the core modifications in the Dockerfile.
Linked Issues check ✅ Passed PR fulfills all coding requirements from issue #739: bumps OpenClaw to 2026.3.22, widens allowedOrigins to include wildcard and 127.0.0.1:3333, and adds RFC 1918 CIDRs to trustedProxies.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #739 requirements: version bump, CORS origin widening, and trusted proxy expansion; no unrelated modifications present.
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
Copy Markdown
Contributor

@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 thread 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
Copy Markdown
Contributor

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.

Comment thread Dockerfile
'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
Copy Markdown
Contributor

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
Copy Markdown
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
@cluster2600 cluster2600 force-pushed the fix/openclaw-2026.3.22-and-cors branch from 41f85f9 to eb87d08 Compare March 25, 2026 19:32
- 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>
@cluster2600 cluster2600 force-pushed the fix/openclaw-2026.3.22-and-cors branch from eb87d08 to ee6f0de Compare March 30, 2026 06:12
@tkg61
Copy link
Copy Markdown

tkg61 commented Apr 7, 2026

Any status on this? Would really like to upgrade versions

@cluster2600
Copy link
Copy Markdown
Contributor Author

Closing — OpenClaw has been bumped to 2026.4.2 on main (#1522), which is past what this PR targeted. The Dockerfile also moved to a multi-stage base image architecture in the meantime, so this would need a full rewrite. Not worth it.

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

3 participants