Skip to content

fix(onboard): honor NEMOCLAW_PROXY_HOST/PORT env at sandbox build time (#1409)#1563

Merged
cv merged 1 commit into
NVIDIA:mainfrom
ColinM-sys:fix/1409-honor-nemoclaw-proxy-host-port-env
Apr 8, 2026
Merged

fix(onboard): honor NEMOCLAW_PROXY_HOST/PORT env at sandbox build time (#1409)#1563
cv merged 1 commit into
NVIDIA:mainfrom
ColinM-sys:fix/1409-honor-nemoclaw-proxy-host-port-env

Conversation

@ColinM-sys

@ColinM-sys ColinM-sys commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #1409.

NEMOCLAW_PROXY_HOST and NEMOCLAW_PROXY_PORT exported in the host shell before nemoclaw onboard are silently dropped — the resulting sandbox always uses the default 10.200.0.1:3128 proxy.

Root cause

scripts/nemoclaw-start.sh:332 reads ${NEMOCLAW_PROXY_HOST:-10.200.0.1} from container env with the documented intent that operators can override the gateway proxy at sandbox creation time. The host-side plumbing was missing:

  • The Dockerfile did not declare ARG NEMOCLAW_PROXY_HOST / NEMOCLAW_PROXY_PORT and did not promote them to ENV.
  • patchStagedDockerfile() in bin/lib/onboard.js did not read either variable from process.env.

So even though the in-container script was correctly written to honor the override, nothing in the host-side onboard flow ever passed the values into the build context. The sandbox always landed on the defaults.

Fix

Three symmetrical changes — same pattern the project already uses for NEMOCLAW_MODEL, CHAT_UI_URL, etc.:

  1. Dockerfile — declare ARG NEMOCLAW_PROXY_HOST=10.200.0.1 and ARG NEMOCLAW_PROXY_PORT=3128 (preserving existing defaults), and add them to the existing ENV block so the in-container start script sees them.

  2. bin/lib/onboard.js — in patchStagedDockerfile(), if process.env.NEMOCLAW_PROXY_HOST / NEMOCLAW_PROXY_PORT are set and pass strict regex validation (^[A-Za-z0-9._:-]+$ for host, ^[0-9]{1,5}$ for port), bake the values into the staged Dockerfile via the same ARG-line replacement pattern used for the other deploy-time settings. Malformed input is rejected so a hostile process.env cannot break out of the ARG line into arbitrary Dockerfile directives.

  3. test/onboard.test.js — three regression tests:

    • Override values in env → assert the staged Dockerfile contains them.
    • No env vars set → assert defaults are preserved.
    • Malformed env (e.g. NEMOCLAW_PROXY_HOST=1.2.3.4\nRUN rm -rf /) → assert defaults are preserved and the injected RUN does not appear in the patched Dockerfile.

Test plan

  • vitest run test/onboard.test.js -t "patches the staged Dockerfile" — 3/3 existing assertions pass (no regression).
  • vitest run test/onboard.test.js -t "1409" — 3/3 new regression tests pass.
  • Not verified locally: full host → onboard → sandbox build → echo $HTTP_PROXY inside sandbox repro from the issue. The patched mechanism uses the exact same ARGENV → start-script chain that already works for NEMOCLAW_MODEL, CHAT_UI_URL, NEMOCLAW_DISABLE_DEVICE_AUTH, etc., so the live behavior should follow, but a maintainer or reporter with the original repro environment is welcome to confirm.

Security note

The two regex validators are deliberate, not theatrical. patchStagedDockerfile() writes to a Dockerfile that is then handed to docker build, so an unvalidated process.env value containing a newline could inject arbitrary build steps. The ^[A-Za-z0-9._:-]+$ host regex covers IPv4, hostnames, and bracket-less IPv6 cases; the ^[0-9]{1,5}$ port regex covers 0–65535 (with the natural-but-acceptable false positive of 5-digit values above 65535, which Docker/the kernel will reject downstream anyway).

Summary by CodeRabbit

  • New Features

    • Added support for configurable proxy settings. Users can now set proxy host and port via environment variables, which will be automatically applied during container builds with input validation.
  • Tests

    • Added comprehensive test coverage for proxy configuration handling, including validation of malformed inputs.

The sandbox-side nemoclaw-start.sh already reads NEMOCLAW_PROXY_HOST and
NEMOCLAW_PROXY_PORT from its environment with the documented intent that
operators can override the default 10.200.0.1:3128 egress proxy at
sandbox creation time. The plumbing on the host side was missing,
however: the Dockerfile declared no ARG for either variable and
patchStagedDockerfile() never read them from process.env, so values
exported in the host shell before 'nemoclaw onboard' were silently
dropped and the sandbox always landed on the defaults.

Three changes:

- Dockerfile: declare ARG NEMOCLAW_PROXY_HOST and ARG NEMOCLAW_PROXY_PORT
  with the existing defaults, and promote them to ENV alongside the
  other build-arg-derived envs so the in-container start script sees them.
- bin/lib/onboard.js: in patchStagedDockerfile(), if process.env contains
  NEMOCLAW_PROXY_HOST / NEMOCLAW_PROXY_PORT, validate them against tight
  regexes and bake the values into the staged Dockerfile via the same
  ARG-line replacement pattern used for the other deploy-time settings.
  Malformed values are rejected so an attacker who controls the host env
  cannot break out of the ARG line into arbitrary Dockerfile directives.
- test/onboard.test.js: three regression tests covering (a) the
  override-baked-in case, (b) the env-unset defaults-preserved case, and
  (c) the malformed-input-rejected case.

Closes NVIDIA#1409
@coderabbitai

coderabbitai Bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The Dockerfile declares NEMOCLAW_PROXY_HOST and NEMOCLAW_PROXY_PORT as build arguments with defaults (10.200.0.1 and 3128), while patchStagedDockerfile() in the onboard script conditionally injects host environment values during Dockerfile preparation. Input validation prevents malformed or malicious values from being injected, with comprehensive regression tests covering configured, unconfigured, and invalid proxy scenarios.

Changes

Cohort / File(s) Summary
Dockerfile Configuration
Dockerfile
Added NEMOCLAW_PROXY_HOST and NEMOCLAW_PROXY_PORT build arguments with defaults (10.200.0.1, 3128) and promoted them to runtime environment variables.
Proxy Injection Logic
bin/lib/onboard.js
Extended patchStagedDockerfile() to conditionally inject proxy host/port from host environment when present, with regex validation for host (^[A-Za-z0-9._:-]+$) and numeric validation for port (^[0-9]{1,5}$).
Regression Tests
test/onboard.test.js
Added three test cases covering: configured proxy override, unconfigured defaults preservation, and malicious payload rejection when env vars are malformed or contain injection attempts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A proxy path, once lost in the dark,
Now finds its way through validation's arc,
From host to Dockerfile, safe and clean,
No shell exploits shall sneak in between,
The sandbox hops toward custom routes true! 🛤️

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: enabling host-side environment variables NEMOCLAW_PROXY_HOST and NEMOCLAW_PROXY_PORT to be honored during sandbox build time, directly addressing the bug reported in issue #1409.
Linked Issues check ✅ Passed The pull request successfully implements all coding requirements from issue #1409: Dockerfile now exports proxy host/port variables with defaults, patchStagedDockerfile() validates and injects them from process.env, and comprehensive tests cover normal/edge/malicious cases.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #1409: Dockerfile modifications add necessary ARG/ENV declarations, onboard.js changes implement host env propagation with validation, and test additions cover the new functionality without extraneous modifications.

✏️ 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.

@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 the current code and only fix it if needed.

Inline comments:
In `@bin/lib/onboard.js`:
- Around line 943-956: The proxy port check only enforces numeric format via
PROXY_PORT_RE and can accept invalid ports like 00000 or >65535; update the
validation around proxyPortEnv used in the ARG replacement to (1) parse the
value with parseInt(proxyPortEnv, 10), (2) ensure the parsed number is between 1
and 65535 inclusive, and (optionally) reject values with leading zeros by
verifying String(parsed) === proxyPortEnv to avoid things like "00000"; only
perform the dockerfile.replace when the numeric range check passes. Reference
the symbols PROXY_PORT_RE, proxyPortEnv, and the dockerfile.replace block for
where to change the logic.
🪄 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: Pro

Run ID: af6dace1-8af6-4cd7-9719-55ecc31cde07

📥 Commits

Reviewing files that changed from the base of the PR and between bbec268 and c2c262f.

📒 Files selected for processing (3)
  • Dockerfile
  • bin/lib/onboard.js
  • test/onboard.test.js

Comment thread bin/lib/onboard.js
Comment on lines +943 to +956
const PROXY_PORT_RE = /^[0-9]{1,5}$/;
const proxyHostEnv = process.env.NEMOCLAW_PROXY_HOST;
if (proxyHostEnv && PROXY_HOST_RE.test(proxyHostEnv)) {
dockerfile = dockerfile.replace(
/^ARG NEMOCLAW_PROXY_HOST=.*$/m,
`ARG NEMOCLAW_PROXY_HOST=${proxyHostEnv}`,
);
}
const proxyPortEnv = process.env.NEMOCLAW_PROXY_PORT;
if (proxyPortEnv && PROXY_PORT_RE.test(proxyPortEnv)) {
dockerfile = dockerfile.replace(
/^ARG NEMOCLAW_PROXY_PORT=.*$/m,
`ARG NEMOCLAW_PROXY_PORT=${proxyPortEnv}`,
);

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

Validate proxy port range, not just format.

Line 943 allows values like 00000 and 99999, which are not valid TCP ports, yet they are baked into the Dockerfile at Line 955 and can silently break proxy egress.

Suggested fix
-  const PROXY_PORT_RE = /^[0-9]{1,5}$/;
+  const PROXY_PORT_RE = /^[0-9]{1,5}$/;

   const proxyPortEnv = process.env.NEMOCLAW_PROXY_PORT;
-  if (proxyPortEnv && PROXY_PORT_RE.test(proxyPortEnv)) {
+  if (proxyPortEnv !== undefined && proxyPortEnv !== "") {
+    if (!PROXY_PORT_RE.test(proxyPortEnv)) {
+      throw new Error("Invalid NEMOCLAW_PROXY_PORT: expected numeric TCP port (1-65535)");
+    }
+    const proxyPort = Number(proxyPortEnv);
+    if (!Number.isInteger(proxyPort) || proxyPort < 1 || proxyPort > 65535) {
+      throw new Error("Invalid NEMOCLAW_PROXY_PORT: expected numeric TCP port (1-65535)");
+    }
     dockerfile = dockerfile.replace(
       /^ARG NEMOCLAW_PROXY_PORT=.*$/m,
-      `ARG NEMOCLAW_PROXY_PORT=${proxyPortEnv}`,
+      `ARG NEMOCLAW_PROXY_PORT=${proxyPort}`,
     );
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/onboard.js` around lines 943 - 956, The proxy port check only
enforces numeric format via PROXY_PORT_RE and can accept invalid ports like
00000 or >65535; update the validation around proxyPortEnv used in the ARG
replacement to (1) parse the value with parseInt(proxyPortEnv, 10), (2) ensure
the parsed number is between 1 and 65535 inclusive, and (optionally) reject
values with leading zeros by verifying String(parsed) === proxyPortEnv to avoid
things like "00000"; only perform the dockerfile.replace when the numeric range
check passes. Reference the symbols PROXY_PORT_RE, proxyPortEnv, and the
dockerfile.replace block for where to change the logic.

@wscurran wscurran added bug Something fails against expected or documented behavior NemoClaw CLI labels Apr 8, 2026
@wscurran

wscurran commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this fix, which proposes a way to ensure NEMOCLAW_PROXY_HOST and NEMOCLAW_PROXY_PORT are properly passed into the sandbox build context.


Possibly related open issues:

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

LGTM — security review WARNING (non-blocking).

Approved with one suggestion:

  • Port range validation: The regex ^[0-9]{1,5}$ accepts invalid TCP ports (00000, 99999, 65536). Consider adding parseInt(port, 10) with a 1-65535 range check after the regex. This prevents silent misconfiguration — not an injection risk, but an operator could get a non-functional proxy. CodeRabbit flagged this too.

Otherwise excellent:

  • Strict anchored regexes prevent Dockerfile injection (newlines, shell metacharacters all blocked)
  • Host regex character set is well-chosen for IPv4/IPv6/hostnames
  • Injection test case (1.2.3.4\nRUN rm -rf /) explicitly verified
  • No SSRF amplification — proxy only affects sandbox-internal HTTP_PROXY, network policies unaffected
  • Actually stricter than existing ARG patching patterns (sets a better precedent)
  • Comprehensive test coverage

No concerns from a security standpoint.

@cv cv merged commit 7555f6b into NVIDIA:main Apr 8, 2026
2 checks passed
miyoungc added a commit that referenced this pull request Apr 9, 2026
## Summary
- Document `nemoclaw credentials list` and `nemoclaw credentials reset`
commands in commands reference (#1597)
- Add `--dry-run` flag documentation for `policy-add` (#1276)
- Update policy presets table: remove `docker` (#1647), add `brave` and
`brew`, update HuggingFace endpoint (#1540)
- Document `NEMOCLAW_LOCAL_INFERENCE_TIMEOUT` env var for local
providers (#1620)
- Document `NEMOCLAW_PROXY_HOST`/`NEMOCLAW_PROXY_PORT` env vars (#1563)
- Add troubleshooting entries for Docker group permissions (#1614),
sandbox survival after gateway restart (#1587), and proxy configuration
- Regenerate `nemoclaw-user-*` skills from updated docs

## Test plan
- [x] `make docs` builds without warnings
- [x] All pre-commit and pre-push hooks pass
- [ ] Verify rendered pages in docs site preview

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

## Summary by CodeRabbit

* **New Features**
* Added `nemoclaw credentials list` command to display stored credential
names
* Added `nemoclaw credentials reset <KEY>` command with `--yes` flag to
remove credentials
  * Added `--dry-run` flag for policy-add to preview endpoint changes
  * New policy presets: `brave` and `brew`
* New configuration options: `NEMOCLAW_LOCAL_INFERENCE_TIMEOUT`,
`NEMOCLAW_PROXY_HOST`, and `NEMOCLAW_PROXY_PORT`

* **Documentation**
* Expanded troubleshooting guides for Docker permissions, sandbox
connectivity, local inference timeouts, and proxy configuration

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

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
gemini2026 pushed a commit to gemini2026/NemoClaw that referenced this pull request Apr 14, 2026
NVIDIA#1409) (NVIDIA#1563)

## Summary

Closes NVIDIA#1409.

`NEMOCLAW_PROXY_HOST` and `NEMOCLAW_PROXY_PORT` exported in the host
shell before `nemoclaw onboard` are silently dropped — the resulting
sandbox always uses the default `10.200.0.1:3128` proxy.

## Root cause

`scripts/nemoclaw-start.sh:332` reads
`${NEMOCLAW_PROXY_HOST:-10.200.0.1}` from container env with the
documented intent that operators can override the gateway proxy at
sandbox creation time. The host-side plumbing was missing:

- The `Dockerfile` did not declare `ARG NEMOCLAW_PROXY_HOST` /
`NEMOCLAW_PROXY_PORT` and did not promote them to `ENV`.
- `patchStagedDockerfile()` in `bin/lib/onboard.js` did not read either
variable from `process.env`.

So even though the in-container script was correctly written to honor
the override, nothing in the host-side onboard flow ever passed the
values into the build context. The sandbox always landed on the
defaults.

## Fix

Three symmetrical changes — same pattern the project already uses for
`NEMOCLAW_MODEL`, `CHAT_UI_URL`, etc.:

1. **`Dockerfile`** — declare `ARG NEMOCLAW_PROXY_HOST=10.200.0.1` and
`ARG NEMOCLAW_PROXY_PORT=3128` (preserving existing defaults), and add
them to the existing `ENV` block so the in-container start script sees
them.

2. **`bin/lib/onboard.js`** — in `patchStagedDockerfile()`, if
`process.env.NEMOCLAW_PROXY_HOST` / `NEMOCLAW_PROXY_PORT` are set and
pass strict regex validation (`^[A-Za-z0-9._:-]+$` for host,
`^[0-9]{1,5}$` for port), bake the values into the staged Dockerfile via
the same `ARG`-line replacement pattern used for the other deploy-time
settings. Malformed input is rejected so a hostile `process.env` cannot
break out of the `ARG` line into arbitrary Dockerfile directives.

3. **`test/onboard.test.js`** — three regression tests:
- Override values in env → assert the staged Dockerfile contains them.
   - No env vars set → assert defaults are preserved.
- Malformed env (e.g. `NEMOCLAW_PROXY_HOST=1.2.3.4\nRUN rm -rf /`) →
assert defaults are preserved and the injected `RUN` does not appear in
the patched Dockerfile.

## Test plan

- [x] `vitest run test/onboard.test.js -t "patches the staged
Dockerfile"` — 3/3 existing assertions pass (no regression).
- [x] `vitest run test/onboard.test.js -t "1409"` — 3/3 new regression
tests pass.
- [ ] **Not verified locally:** full host → onboard → sandbox build →
`echo $HTTP_PROXY` inside sandbox repro from the issue. The patched
mechanism uses the exact same `ARG` → `ENV` → start-script chain that
already works for `NEMOCLAW_MODEL`, `CHAT_UI_URL`,
`NEMOCLAW_DISABLE_DEVICE_AUTH`, etc., so the live behavior should
follow, but a maintainer or reporter with the original repro environment
is welcome to confirm.

## Security note

The two regex validators are deliberate, not theatrical.
`patchStagedDockerfile()` writes to a Dockerfile that is then handed to
`docker build`, so an unvalidated `process.env` value containing a
newline could inject arbitrary build steps. The `^[A-Za-z0-9._:-]+$`
host regex covers IPv4, hostnames, and bracket-less IPv6 cases; the
`^[0-9]{1,5}$` port regex covers 0–65535 (with the
natural-but-acceptable false positive of 5-digit values above 65535,
which Docker/the kernel will reject downstream anyway).


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

## Summary by CodeRabbit

* **New Features**
* Added support for configurable proxy settings. Users can now set proxy
host and port via environment variables, which will be automatically
applied during container builds with input validation.

* **Tests**
* Added comprehensive test coverage for proxy configuration handling,
including validation of malformed inputs.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
gemini2026 pushed a commit to gemini2026/NemoClaw that referenced this pull request Apr 14, 2026
## Summary
- Document `nemoclaw credentials list` and `nemoclaw credentials reset`
commands in commands reference (NVIDIA#1597)
- Add `--dry-run` flag documentation for `policy-add` (NVIDIA#1276)
- Update policy presets table: remove `docker` (NVIDIA#1647), add `brave` and
`brew`, update HuggingFace endpoint (NVIDIA#1540)
- Document `NEMOCLAW_LOCAL_INFERENCE_TIMEOUT` env var for local
providers (NVIDIA#1620)
- Document `NEMOCLAW_PROXY_HOST`/`NEMOCLAW_PROXY_PORT` env vars (NVIDIA#1563)
- Add troubleshooting entries for Docker group permissions (NVIDIA#1614),
sandbox survival after gateway restart (NVIDIA#1587), and proxy configuration
- Regenerate `nemoclaw-user-*` skills from updated docs

## Test plan
- [x] `make docs` builds without warnings
- [x] All pre-commit and pre-push hooks pass
- [ ] Verify rendered pages in docs site preview

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

## Summary by CodeRabbit

* **New Features**
* Added `nemoclaw credentials list` command to display stored credential
names
* Added `nemoclaw credentials reset <KEY>` command with `--yes` flag to
remove credentials
  * Added `--dry-run` flag for policy-add to preview endpoint changes
  * New policy presets: `brave` and `brew`
* New configuration options: `NEMOCLAW_LOCAL_INFERENCE_TIMEOUT`,
`NEMOCLAW_PROXY_HOST`, and `NEMOCLAW_PROXY_PORT`

* **Documentation**
* Expanded troubleshooting guides for Docker permissions, sandbox
connectivity, local inference timeouts, and proxy configuration

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

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output area: packaging Packages, images, registries, installers, or distribution bug-fix PR fixes a bug or regression platform: container Affects Docker, containerd, Podman, or images and removed area: packaging Packages, images, registries, installers, or distribution NemoClaw CLI bug Something fails against expected or documented behavior labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression platform: container Affects Docker, containerd, Podman, or images

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[All Platforms][Proxy] NEMOCLAW_PROXY_HOST / NEMOCLAW_PROXY_PORT are ignored; sandbox still uses default proxy 10.200.0.1:3128

3 participants