Skip to content

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

Open
ColinM-sys wants to merge 1 commit intoNVIDIA:mainfrom
ColinM-sys:fix/1409-honor-nemoclaw-proxy-host-port-env
Open

fix(onboard): honor NEMOCLAW_PROXY_HOST/PORT env at sandbox build time (#1409)#1563
ColinM-sys wants to merge 1 commit intoNVIDIA:mainfrom
ColinM-sys:fix/1409-honor-nemoclaw-proxy-host-port-env

Conversation

@ColinM-sys
Copy link
Copy Markdown

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

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
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 7, 2026

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

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

1 participant