Skip to content

fix: bake CHAT_UI_URL into Docker build for remote dashboard access - #812

Merged
cv merged 2 commits into
mainfrom
fix/chat-ui-url-build-arg
Apr 3, 2026
Merged

fix: bake CHAT_UI_URL into Docker build for remote dashboard access#812
cv merged 2 commits into
mainfrom
fix/chat-ui-url-build-arg

Conversation

@ericksoa

@ericksoa ericksoa commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • setup.sh and onboard.js passed CHAT_UI_URL only as a runtime env var, but the gateway allowedOrigins are generated at build time and locked immutable (root:root 444 + Landlock). Remote browsers hit "origin not allowed" because the build always used the default localhost origin.
  • Sed the ARG CHAT_UI_URL line in the build-context Dockerfile copy when the env var is set, so the build-time config generator writes the correct allowedOrigins. URL is validated before interpolation to prevent injection.
  • Forward CHAT_UI_URL through brev-setup.sh and warn on headless hosts when it is unset.
  • Document CHAT_UI_URL requirement for remote deployments.

Fixes #795, fixes #20

Test plan

  • Existing security-c2-dockerfile-injection tests pass (13/13)
  • Full test suite passes (306/307, 1 pre-existing flaky timeout)
  • URL validation rejects all injection vectors (tested: |, $(), backticks, &, ;, spaces)
  • setup.sh without CHAT_UI_URL behaves identically to before (no regression)
  • CHAT_UI_URL=https://openclaw0-test.brevlab.com ./scripts/setup.sh bakes origin into build

Summary by CodeRabbit

Release Notes

  • Documentation

    • Added instructions for remote dashboard access with CHAT_UI_URL configuration for Brev deployments
    • Clarified setup differences between SSH port-forwarding and public URL scenarios
  • Improvements

    • Setup script now logs CHAT_UI_URL configuration and warns about missing remote access settings on headless systems

setup.sh and onboard.js passed CHAT_UI_URL only as a runtime env var,
but the gateway allowedOrigins are generated at build time and locked
immutable (root:root 444 + Landlock).  Remote browsers hit "origin not
allowed" because the build always used the default localhost origin.

Sed the ARG CHAT_UI_URL line in the build-context Dockerfile copy when
the env var is set, so the build-time config generator writes the
correct allowedOrigins.  URL is validated before interpolation to
prevent injection.

Also forward CHAT_UI_URL through brev-setup.sh and warn on headless
hosts when it is unset.

Fixes #795, fixes #20
@ericksoa ericksoa self-assigned this Mar 24, 2026
@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

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: cbc6442b-5e72-4230-8b61-f017b2910d6d

📥 Commits

Reviewing files that changed from the base of the PR and between 71ec390 and a212c2e.

📒 Files selected for processing (3)
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/brev-setup.sh
  • test/runner.test.js
✅ Files skipped from review due to trivial changes (2)
  • test/runner.test.js
  • docs/deployment/deploy-to-remote-gpu.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/brev-setup.sh

📝 Walkthrough

Walkthrough

Three files are updated to address remote dashboard access for NemoClaw on Brev: documentation is added describing the CHAT_UI_URL configuration requirement and browser-origin allowlisting mechanism; the setup script conditionally exports CHAT_UI_URL and emits warnings when remote access is misconfigured; and a test comment is annotated for gitleaks scanning.

Changes

Cohort / File(s) Summary
Documentation
docs/deployment/deploy-to-remote-gpu.md
New "Remote Dashboard Access" section documenting the CHAT_UI_URL configuration requirement, explaining browser-origin allowlisting embedded during build, and clarifying when this setting is necessary (Brev public URLs vs. local SSH port-forwarding).
Setup Script Enhancement
scripts/brev-setup.sh
Conditional logic to export CHAT_UI_URL and log its value when non-empty. Emits three warning messages when remote browser access would fail due to missing origin allowlisting (triggered when CHAT_UI_URL is unset and no local X11 display is detected).
Test Annotation
test/runner.test.js
Inline // gitleaks:allow comment added to stdout test data containing a URL with credentials, with no changes to test logic or assertions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 The Brev dashboard now finds its way,
With origins set before deploy day,
Warnings whisper when config's askew,
Remote access flows—a rabbit's breakthrough! 🌐✨

🚥 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 'fix: bake CHAT_UI_URL into Docker build for remote dashboard access' accurately captures the main change—incorporating CHAT_UI_URL at Docker build time to fix remote dashboard access failures.
Linked Issues check ✅ Passed The PR addresses the core requirements from both linked issues: it fixes the 'origin not allowed' error (#795) by baking CHAT_UI_URL into the Docker build, and enables remote dashboard access (#20) through documentation and setup flow changes.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the stated objectives: documentation updates for remote access, script modifications to forward CHAT_UI_URL, and a minor test comment addition for security scanning.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chat-ui-url-build-arg

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

@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.

🧹 Nitpick comments (2)
docs/deployment/deploy-to-remote-gpu.md (2)

80-84: Multiple sentences on the same source line.

This paragraph contains three sentences that should each be on their own line for diff readability.
As per coding guidelines: "One sentence per line in source (makes diffs readable). Flag paragraphs where multiple sentences appear on the same line."

📝 Suggested reformat
-The NemoClaw dashboard validates the browser origin against an allowlist baked
-into the sandbox image at build time.  By default the allowlist only contains
-`http://127.0.0.1:18789`.  When accessing the dashboard from a remote browser
-(for example through a Brev public URL or an SSH port-forward), set
-`CHAT_UI_URL` to the origin the browser will use **before** running setup:
+The NemoClaw dashboard validates the browser origin against an allowlist baked into the sandbox image at build time.
+By default the allowlist only contains `http://127.0.0.1:18789`.
+When accessing the dashboard from a remote browser (for example through a Brev public URL or an SSH port-forward), set `CHAT_UI_URL` to the origin the browser will use **before** running setup:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/deployment/deploy-to-remote-gpu.md` around lines 80 - 84, The paragraph
in docs/deployment/deploy-to-remote-gpu.md packs three sentences into one line;
split each sentence onto its own source line to follow "one sentence per line"
guideline so diffs are readable. Locate the paragraph mentioning NemoClaw, the
allowlist default `http://127.0.0.1:18789`, the remote browser access examples
(Brev public URL / SSH port-forward), and the `CHAT_UI_URL` instruction, and
break it into three separate lines—one for the allowlist/default origin, one for
the remote access examples, and one for the instruction to set `CHAT_UI_URL`
before running setup.

95-97: Multiple sentences on the same source line within admonition.

The note contains two sentences that should each appear on their own line.
As per coding guidelines: "One sentence per line in source (makes diffs readable)."

📝 Suggested reformat
 :::{note}
-On Brev, set `CHAT_UI_URL` in the launchable environment configuration so it is
-available when the setup script builds the sandbox image.  If `CHAT_UI_URL` is
-not set on a headless host, `brev-setup.sh` prints a warning.
+On Brev, set `CHAT_UI_URL` in the launchable environment configuration so it is available when the setup script builds the sandbox image.
+If `CHAT_UI_URL` is not set on a headless host, `brev-setup.sh` prints a warning.
 :::
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/deployment/deploy-to-remote-gpu.md` around lines 95 - 97, The admonition
text mentioning CHAT_UI_URL and brev-setup.sh contains multiple sentences on one
source line; edit the note so each sentence is on its own source line (e.g.,
split "On Brev, set `CHAT_UI_URL`... image." and "If `CHAT_UI_URL` is not set on
a headless host, `brev-setup.sh` prints a warning." into two separate lines) to
follow the "one sentence per line" guideline and improve diff readability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/deployment/deploy-to-remote-gpu.md`:
- Around line 80-84: The paragraph in docs/deployment/deploy-to-remote-gpu.md
packs three sentences into one line; split each sentence onto its own source
line to follow "one sentence per line" guideline so diffs are readable. Locate
the paragraph mentioning NemoClaw, the allowlist default
`http://127.0.0.1:18789`, the remote browser access examples (Brev public URL /
SSH port-forward), and the `CHAT_UI_URL` instruction, and break it into three
separate lines—one for the allowlist/default origin, one for the remote access
examples, and one for the instruction to set `CHAT_UI_URL` before running setup.
- Around line 95-97: The admonition text mentioning CHAT_UI_URL and
brev-setup.sh contains multiple sentences on one source line; edit the note so
each sentence is on its own source line (e.g., split "On Brev, set
`CHAT_UI_URL`... image." and "If `CHAT_UI_URL` is not set on a headless host,
`brev-setup.sh` prints a warning." into two separate lines) to follow the "one
sentence per line" guideline and improve diff readability.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7746d00e-fb3d-47b1-a245-375d688efdb2

📥 Commits

Reviewing files that changed from the base of the PR and between fb03994 and 71ec390.

📒 Files selected for processing (4)
  • bin/lib/onboard.js
  • docs/deployment/deploy-to-remote-gpu.md
  • scripts/brev-setup.sh
  • scripts/setup.sh

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few suggestions — nothing blocking, all optional.

Comment thread bin/lib/onboard.js Outdated
Comment on lines +550 to +551
const chatUiUrl = process.env.CHAT_UI_URL || 'http://127.0.0.1:18789';
if (chatUiUrl !== 'http://127.0.0.1:18789') {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: the default URL is repeated as a magic string here and must match the Dockerfile ARG default. If the Dockerfile default ever changes, this comparison silently breaks. Consider extracting a constant:

Suggested change
const chatUiUrl = process.env.CHAT_UI_URL || 'http://127.0.0.1:18789';
if (chatUiUrl !== 'http://127.0.0.1:18789') {
const DEFAULT_CHAT_UI_URL = 'http://127.0.0.1:18789';
const chatUiUrl = process.env.CHAT_UI_URL || DEFAULT_CHAT_UI_URL;
if (chatUiUrl !== DEFAULT_CHAT_UI_URL) {

Comment thread bin/lib/onboard.js Outdated
// Ref: https://github.com/NVIDIA/NemoClaw/issues/795
const chatUiUrl = process.env.CHAT_UI_URL || 'http://127.0.0.1:18789';
if (chatUiUrl !== 'http://127.0.0.1:18789') {
if (/^https?:\/\/[a-zA-Z0-9._:-]+(\/[a-zA-Z0-9._/~%-]*)?$/.test(chatUiUrl)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This regex is duplicated in scripts/setup.sh:198 (bash version). If one gets updated without the other, you get inconsistent validation depending on the entrypoint. Consider adding a comment in each location cross-referencing the other, e.g.:

// NOTE: keep in sync with scripts/setup.sh URL validation regex

Comment thread scripts/setup.sh Outdated
Comment on lines 207 to 220
CHAT_UI_ENV=""
if [ -n "${CHAT_UI_URL:-}" ]; then
CHAT_UI_ENV="CHAT_UI_URL=$CHAT_UI_URL"
fi

# Capture full output to a temp file so we can filter for display but still
# detect failures. The raw log is kept on failure for debugging.
CREATE_LOG=$(mktemp /tmp/nemoclaw-create-XXXXXX.log)
set +e
# shellcheck disable=SC2086 # intentional word-split on CHAT_UI_ENV (validated URL, no spaces)
openshell sandbox create --from "$BUILD_CTX/Dockerfile" --name "$SANDBOX_NAME" \
--provider nvidia-nim \
-- env NVIDIA_API_KEY="$NVIDIA_API_KEY" >"$CREATE_LOG" 2>&1
-- env NVIDIA_API_KEY="$NVIDIA_API_KEY" $CHAT_UI_ENV >"$CREATE_LOG" 2>&1
CREATE_RC=$?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The word-splitting approach works but requires a shellcheck suppression and is fragile if the regex ever allows spaces. Consider using a bash array instead — more idiomatic and avoids the suppression entirely:

Suggested change
CHAT_UI_ENV=""
if [ -n "${CHAT_UI_URL:-}" ]; then
CHAT_UI_ENV="CHAT_UI_URL=$CHAT_UI_URL"
fi
# Capture full output to a temp file so we can filter for display but still
# detect failures. The raw log is kept on failure for debugging.
CREATE_LOG=$(mktemp /tmp/nemoclaw-create-XXXXXX.log)
set +e
# shellcheck disable=SC2086 # intentional word-split on CHAT_UI_ENV (validated URL, no spaces)
openshell sandbox create --from "$BUILD_CTX/Dockerfile" --name "$SANDBOX_NAME" \
--provider nvidia-nim \
-- env NVIDIA_API_KEY="$NVIDIA_API_KEY" >"$CREATE_LOG" 2>&1
-- env NVIDIA_API_KEY="$NVIDIA_API_KEY" $CHAT_UI_ENV >"$CREATE_LOG" 2>&1
CREATE_RC=$?
# Build the runtime env args array.
ENV_ARGS=(NVIDIA_API_KEY="$NVIDIA_API_KEY")
if [ -n "${CHAT_UI_URL:-}" ]; then
ENV_ARGS+=(CHAT_UI_URL="$CHAT_UI_URL")
fi
# Capture full output to a temp file so we can filter for display but still
# detect failures. The raw log is kept on failure for debugging.
CREATE_LOG=$(mktemp /tmp/nemoclaw-create-XXXXXX.log)
set +e
openshell sandbox create --from "$BUILD_CTX/Dockerfile" --name "$SANDBOX_NAME" \
--provider nvidia-nim \
-- env "${ENV_ARGS[@]}" >"$CREATE_LOG" 2>&1

ericksoa added a commit that referenced this pull request Mar 24, 2026
Keep main's patchStagedDockerfile and formatEnvAssignment from #812,
while preserving the security fix: strip NVIDIA_API_KEY from sandbox
environment and delete from process.env after provider config storage.
@harrism

harrism commented Mar 26, 2026

Copy link
Copy Markdown

+1 This fixes a usability issue for me.

@cv
cv enabled auto-merge (squash) April 2, 2026 05:47
# Conflicts:
#	bin/lib/onboard.js
#	scripts/brev-setup.sh
#	scripts/setup.sh
@cv
cv merged commit 6386bf8 into main Apr 3, 2026
13 checks passed
@cv
cv deleted the fix/chat-ui-url-build-arg branch April 3, 2026 01:12
cjagwani pushed a commit to fdzdev/NemoClaw that referenced this pull request Apr 3, 2026
…VIDIA#812)

## Summary

- `setup.sh` and `onboard.js` passed `CHAT_UI_URL` only as a runtime env
var, but the gateway `allowedOrigins` are generated at **build time**
and locked immutable (`root:root 444` + Landlock). Remote browsers hit
"origin not allowed" because the build always used the default localhost
origin.
- Sed the `ARG CHAT_UI_URL` line in the build-context Dockerfile copy
when the env var is set, so the build-time config generator writes the
correct `allowedOrigins`. URL is validated before interpolation to
prevent injection.
- Forward `CHAT_UI_URL` through `brev-setup.sh` and warn on headless
hosts when it is unset.
- Document `CHAT_UI_URL` requirement for remote deployments.

Fixes NVIDIA#795, fixes NVIDIA#20

## Test plan

- [ ] Existing `security-c2-dockerfile-injection` tests pass (13/13)
- [ ] Full test suite passes (306/307, 1 pre-existing flaky timeout)
- [ ] URL validation rejects all injection vectors (tested: `|`, `$()`,
backticks, `&`, `;`, spaces)
- [ ] `setup.sh` without `CHAT_UI_URL` behaves identically to before (no
regression)
- [ ] `CHAT_UI_URL=https://openclaw0-test.brevlab.com
./scripts/setup.sh` bakes origin into build

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

## Release Notes

* **Documentation**
* Added instructions for remote dashboard access with `CHAT_UI_URL`
configuration for Brev deployments
* Clarified setup differences between SSH port-forwarding and public URL
scenarios

* **Improvements**
* Setup script now logs `CHAT_UI_URL` configuration and warns about
missing remote access settings on headless systems
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Carlos Villela <cvillela@nvidia.com>
lakamsani pushed a commit to lakamsani/NemoClaw that referenced this pull request Apr 4, 2026
…VIDIA#812)

## Summary

- `setup.sh` and `onboard.js` passed `CHAT_UI_URL` only as a runtime env
var, but the gateway `allowedOrigins` are generated at **build time**
and locked immutable (`root:root 444` + Landlock). Remote browsers hit
"origin not allowed" because the build always used the default localhost
origin.
- Sed the `ARG CHAT_UI_URL` line in the build-context Dockerfile copy
when the env var is set, so the build-time config generator writes the
correct `allowedOrigins`. URL is validated before interpolation to
prevent injection.
- Forward `CHAT_UI_URL` through `brev-setup.sh` and warn on headless
hosts when it is unset.
- Document `CHAT_UI_URL` requirement for remote deployments.

Fixes NVIDIA#795, fixes NVIDIA#20

## Test plan

- [ ] Existing `security-c2-dockerfile-injection` tests pass (13/13)
- [ ] Full test suite passes (306/307, 1 pre-existing flaky timeout)
- [ ] URL validation rejects all injection vectors (tested: `|`, `$()`,
backticks, `&`, `;`, spaces)
- [ ] `setup.sh` without `CHAT_UI_URL` behaves identically to before (no
regression)
- [ ] `CHAT_UI_URL=https://openclaw0-test.brevlab.com
./scripts/setup.sh` bakes origin into build

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

## Release Notes

* **Documentation**
* Added instructions for remote dashboard access with `CHAT_UI_URL`
configuration for Brev deployments
* Clarified setup differences between SSH port-forwarding and public URL
scenarios

* **Improvements**
* Setup script now logs `CHAT_UI_URL` configuration and warns about
missing remote access settings on headless systems
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Carlos Villela <cvillela@nvidia.com>
gemini2026 pushed a commit to gemini2026/NemoClaw that referenced this pull request Apr 14, 2026
…VIDIA#812)

## Summary

- `setup.sh` and `onboard.js` passed `CHAT_UI_URL` only as a runtime env
var, but the gateway `allowedOrigins` are generated at **build time**
and locked immutable (`root:root 444` + Landlock). Remote browsers hit
"origin not allowed" because the build always used the default localhost
origin.
- Sed the `ARG CHAT_UI_URL` line in the build-context Dockerfile copy
when the env var is set, so the build-time config generator writes the
correct `allowedOrigins`. URL is validated before interpolation to
prevent injection.
- Forward `CHAT_UI_URL` through `brev-setup.sh` and warn on headless
hosts when it is unset.
- Document `CHAT_UI_URL` requirement for remote deployments.

Fixes NVIDIA#795, fixes NVIDIA#20

## Test plan

- [ ] Existing `security-c2-dockerfile-injection` tests pass (13/13)
- [ ] Full test suite passes (306/307, 1 pre-existing flaky timeout)
- [ ] URL validation rejects all injection vectors (tested: `|`, `$()`,
backticks, `&`, `;`, spaces)
- [ ] `setup.sh` without `CHAT_UI_URL` behaves identically to before (no
regression)
- [ ] `CHAT_UI_URL=https://openclaw0-test.brevlab.com
./scripts/setup.sh` bakes origin into build

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

## Release Notes

* **Documentation**
* Added instructions for remote dashboard access with `CHAT_UI_URL`
configuration for Brev deployments
* Clarified setup differences between SSH port-forwarding and public URL
scenarios

* **Improvements**
* Setup script now logs `CHAT_UI_URL` configuration and warns about
missing remote access settings on headless systems
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Carlos Villela <cvillela@nvidia.com>
senthilr-nv added a commit to senthilr-nv/NemoClaw that referenced this pull request May 4, 2026
…roxy access

When CHAT_UI_URL is set to an HTTPS URL without an explicit port (as
documented for Brev deployments), onboard injects the internal dashboard
port (e.g. :18789) into the origin.  Reverse proxies (Brev Cloudflare
Tunnel, nginx, Caddy) serve on standard :443, so the browser origin
doesn't carry the port — causing "origin not allowed" on the dashboard.

Add the portless origin alongside the port-annotated one in
allowedOrigins for non-loopback URLs.  This is safe (same host) and
covers both direct and proxied access paths.

Prior art: PR NVIDIA#812 and PR NVIDIA#2440 fixed the CHAT_UI_URL plumbing but
the port-override gap remained.

Fixes NVIDIA#3000
Ref: NVIDIA#795, NVIDIA#20

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
senthilr-nv added a commit to senthilr-nv/NemoClaw that referenced this pull request May 4, 2026
…roxy access

When CHAT_UI_URL is set to an HTTPS URL without an explicit port (as
documented for Brev deployments), onboard injects the internal dashboard
port (e.g. :18789) into the origin.  Reverse proxies (Brev Cloudflare
Tunnel, nginx, Caddy) serve on standard :443, so the browser origin
doesn't carry the port — causing "origin not allowed" on the dashboard.

Add the portless origin alongside the port-annotated one in
allowedOrigins for non-loopback URLs.  This is safe (same host) and
covers both direct and proxied access paths.

Prior art: PR NVIDIA#812 and PR NVIDIA#2440 fixed the CHAT_UI_URL plumbing but
the port-override gap remained.

Fixes NVIDIA#3000
Ref: NVIDIA#795, NVIDIA#20

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
senthilr-nv added a commit to senthilr-nv/NemoClaw that referenced this pull request May 4, 2026
…roxy access

When CHAT_UI_URL is set to an HTTPS URL without an explicit port (as
documented for Brev deployments), onboard injects the internal dashboard
port (e.g. :18789) into the origin.  Reverse proxies (Brev Cloudflare
Tunnel, nginx, Caddy) serve on standard :443, so the browser origin
doesn't carry the port — causing "origin not allowed" on the dashboard.

Add the portless origin alongside the port-annotated one in
allowedOrigins for non-loopback URLs.  This is safe (same host) and
covers both direct and proxied access paths.

Prior art: PR NVIDIA#812 and PR NVIDIA#2440 fixed the CHAT_UI_URL plumbing but
the port-override gap remained.

Fixes NVIDIA#3000
Ref: NVIDIA#795, NVIDIA#20

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
senthilr-nv added a commit to senthilr-nv/NemoClaw that referenced this pull request May 4, 2026
…roxy access

When CHAT_UI_URL is set to an HTTPS URL without an explicit port (as
documented for Brev deployments), onboard injects the internal dashboard
port (e.g. :18789) into the origin.  Reverse proxies (Brev Cloudflare
Tunnel, nginx, Caddy) serve on standard :443, so the browser origin
doesn't carry the port — causing "origin not allowed" on the dashboard.

Add the portless origin alongside the port-annotated one in
allowedOrigins for non-loopback URLs.  This is safe (same host) and
covers both direct and proxied access paths.

Prior art: PR NVIDIA#812 and PR NVIDIA#2440 fixed the CHAT_UI_URL plumbing but
the port-override gap remained.

Fixes NVIDIA#3000
Ref: NVIDIA#795, NVIDIA#20

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
senthilr-nv added a commit to senthilr-nv/NemoClaw that referenced this pull request May 4, 2026
…roxy access

When CHAT_UI_URL is set to an HTTPS URL without an explicit port (as
documented for Brev deployments), onboard injects the internal dashboard
port (e.g. :18789) into the origin.  Reverse proxies (Brev Cloudflare
Tunnel, nginx, Caddy) serve on standard :443, so the browser origin
doesn't carry the port — causing "origin not allowed" on the dashboard.

Add the portless origin alongside the port-annotated one in
allowedOrigins for non-loopback URLs.  This is safe (same host) and
covers both direct and proxied access paths.

Prior art: PR NVIDIA#812 and PR NVIDIA#2440 fixed the CHAT_UI_URL plumbing but
the port-override gap remained.

Fixes NVIDIA#3000
Ref: NVIDIA#795, NVIDIA#20

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
ericksoa pushed a commit that referenced this pull request May 4, 2026
…roxy access (#3002)

## Summary

When `CHAT_UI_URL` is set to an HTTPS URL without an explicit port — as
[documented](https://docs.nvidia.com/nemoclaw/latest/deployment/deploy-to-remote-gpu.html#remote-dashboard-access)
for Brev deployments — onboard injects the internal dashboard port
(`:18789`) into the origin via `onboard.ts:4002`. Reverse proxies (Brev
Cloudflare Tunnel, nginx, Caddy, Tailscale Funnel) serve on standard
`:443`, so the browser sends origin `https://host` which doesn't match
`https://host:18789` in `allowedOrigins` — causing "origin not allowed"
on the dashboard.

**Root cause:** `generate-openclaw-config.py` builds `allowedOrigins`
from the port-overridden URL only.

**Fix:** Also include the portless origin for non-loopback URLs. This is
safe (same host) and covers both direct and reverse-proxy access.

## Prior art

PR #812 and PR #2440 fixed the `CHAT_UI_URL` plumbing but the
port-override gap remained. This PR closes the remaining gap from the
#795 / #20 lineage.

## Changes

| File | Change |
|------|--------|
| `scripts/generate-openclaw-config.py` | Add portless origin to
`allowedOrigins` for non-loopback URLs when a port is present |
| `test/generate-openclaw-config.test.ts` | Update existing test to
expect portless origin; add new test for reverse-proxy case |

## Testing

- **Unit tests:** 43/43 passing (`vitest run
test/generate-openclaw-config.test.ts`)
- **Manual verification:** On Brev GCP (`nemoclaw-gcp`, n2-standard-4),
confirmed that adding the portless origin to `allowedOrigins` resolves
the CORS error when accessing
`https://brev-nc-xxx.brevlab.com/chat?session=main`

## What this does NOT fix

- `onboard.ts:4002` still unconditionally overrides the port. A future
improvement could skip the port override when the URL is HTTPS with no
explicit port, but this config-level fix is sufficient and lower-risk.

## Related

- Fixes #3000
- Ref: #795 (Brev dashboard inaccessible — closed)
- Ref: #20 (Remote dashboard access — closed)
- Ref: PR #812 (bake CHAT_UI_URL into Docker build — merged)
- Ref: PR #2440 (inject NEMOCLAW_DASHBOARD_PORT — merged)

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>

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

* **Bug Fixes**
* Improved origin handling: when a configured UI URL includes an
explicit port and is non-loopback, the app accepts both the full origin
(with port) and a portless origin; IPv6 hostnames keep bracket
formatting and duplicate entries are removed. Loopback behavior is
unchanged.

* **Tests**
* Expanded tests to cover ported and portless origins, reverse-proxy
scenarios, IPv6 behavior (including loopback) and resilience to
malformed port values.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
@wscurran wscurran added the bug-fix PR fixes a bug or regression label Jun 8, 2026
@wscurran wscurran added NV QA Bugs found by the NVIDIA QA Team VDR Linked to VDR finding labels Jun 26, 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 NV QA Bugs found by the NVIDIA QA Team VDR Linked to VDR finding

Projects

None yet

4 participants