Skip to content

fix(security): bind Ollama to localhost instead of 0.0.0.0#1140

Open
fdzdev wants to merge 2 commits intoNVIDIA:mainfrom
fdzdev:fix/ollama-localhost-binding
Open

fix(security): bind Ollama to localhost instead of 0.0.0.0#1140
fdzdev wants to merge 2 commits intoNVIDIA:mainfrom
fdzdev:fix/ollama-localhost-binding

Conversation

@fdzdev
Copy link
Copy Markdown
Contributor

@fdzdev fdzdev commented Mar 31, 2026

Summary

  • Replace OLLAMA_HOST=0.0.0.0:11434 with 127.0.0.1:11434 in all three launch sites (CWE-668, NVBUG 6014821)
  • Binding to 0.0.0.0 exposes the Ollama API to the entire LAN, enabling DNS rebinding and unauthorized model access
  • Docker reaches the host via host-gateway which routes to loopback, so 127.0.0.1 is sufficient for sandbox connectivity
  • WSL2 path unchanged (already uses default binding)

Test plan

  • nemoclaw onboard with Ollama on Linux — Ollama binds to 127.0.0.1:11434, not 0.0.0.0
  • Sandbox can still reach Ollama via host-gateway / host.docker.internal
  • nemoclaw onboard on macOS (brew install path) — same localhost binding
  • Ollama API not reachable from other machines on the LAN

Summary by CodeRabbit

  • Bug Fixes

    • Improved Ollama network binding configuration to handle macOS, Linux, and WSL differences correctly.
  • Documentation

    • Clarified platform-specific Ollama setup instructions with guidance for macOS Docker Desktop users.
  • Tests

    • Updated test assertions to account for platform-specific error messages and behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

Platform-specific Ollama binding configuration introduced during onboarding and validation. macOS binds to 127.0.0.1, other Linux systems use 0.0.0.0, and WSL passes no override. Error messages and documentation updated to reflect these platform distinctions.

Changes

Cohort / File(s) Summary
Ollama startup configuration
bin/lib/onboard.js
Conditional platform-specific OLLAMA_HOST binding: 127.0.0.1 on macOS, 0.0.0.0 on non-macOS (excluding WSL), no override on WSL. Applied to both local provider and macOS install paths.
Platform-aware validation
src/lib/local-inference.ts, src/lib/local-inference.test.ts
Error messages now branch on platform: macOS instructs Docker Desktop restart with host networking; other platforms instruct Ollama binding to 0.0.0.0 for container reachability. Test assertions updated for platform-specific error message expectations.
Documentation and logging
spark-install.md, test/e2e/test-gpu-e2e.sh
Documentation clarified as Linux-specific; macOS note added stating Docker Desktop routes host-gateway correctly. Script comments and port-conflict warning updated to reflect Linux-specific container reachability behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Hops cross platforms with glee,
127 for Mac's destiny,
0.0.0.0 for the rest,
WSL gets no address test—
Ollama binds where it should be!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title describes binding Ollama to localhost instead of 0.0.0.0, but the actual changeset implements platform-aware logic: 127.0.0.1 on macOS and 0.0.0.0 on Linux—not a universal switch to localhost. Update the title to reflect the platform-aware approach, such as: 'fix(security): use platform-aware Ollama binding (localhost on macOS, all-interfaces on Linux)' or similar.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

@cv
Copy link
Copy Markdown
Contributor

cv commented Mar 31, 2026

I'm worried this change may break the current local Ollama flow on Linux.

A few places in the repo currently assume sandbox/container reachability requires Ollama to listen on 0.0.0.0:11434 rather than 127.0.0.1:

  • bin/lib/local-inference.js currently returns an error telling the user to ensure Ollama listens on 0.0.0.0:11434 so containers can reach http://host.openshell.internal:11434
  • spark-install.md says the default 127.0.0.1 binding is not reachable from inside the sandbox container
  • test/e2e/test-gpu-e2e.sh documents OLLAMA_HOST=0.0.0.0:11434 as required for containers

So the premise here (that host-gateway reliably routes containers to a host service bound only to loopback) doesn't match the rest of the codebase/docs today.

If that premise has now been validated across supported setups, I think we need to update the validation logic/docs/tests in the same PR, and ideally add a regression test proving a container can still reach http://host.openshell.internal:11434 when Ollama is bound to 127.0.0.1.

Without that, I'd be hesitant to merge this as-is because it looks likely to regress local inference reachability.

On macOS, Docker Desktop routes host-gateway through the VM, so
127.0.0.1 is reachable from containers — bind to localhost to avoid
exposing the Ollama API to the LAN (CWE-668, NVBUG 6014821).

On Linux, containers access the host via the Docker bridge IP, so
0.0.0.0 binding is still required for container reachability.

- Platform-aware OLLAMA_HOST in onboard.js general and macOS paths
- Platform-aware error message in local-inference.js validation
- Updated spark-install.md docs to clarify Linux-only requirement
- Updated test-gpu-e2e.sh comments for platform context
- Added regression tests for platform-specific error messages

Made-with: Cursor
@fdzdev fdzdev force-pushed the fix/ollama-localhost-binding branch from ba19399 to 946e5bb Compare April 3, 2026 05:24
@fdzdev
Copy link
Copy Markdown
Contributor Author

fdzdev commented Apr 3, 2026

Reworked in 946e5bb — you're right, 127.0.0.1 breaks container reachability on Linux.

The fix is now platform-aware: 127.0.0.1 on macOS (Docker Desktop routes host-gateway through the VM) and 0.0.0.0 on Linux (Docker bridge requires it). Updated the validation error message, docs, E2E test comments, and added regression tests for both platforms.

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

🤖 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 2645-2650: The code sets ollamaEnv to "OLLAMA_HOST=0.0.0.0:11434"
for non-WSL Linux which exposes the API off-host; change the non-WSL branch that
currently checks process.platform to use a loopback bind (e.g.,
"OLLAMA_HOST=127.0.0.1:11434") instead of 0.0.0.0 so Linux gets the same
hardening as macOS; update the ollamaEnv assignment (the variable ollamaEnv and
the surrounding isWsl() / process.platform logic) to default to 127.0.0.1 unless
an explicit configuration/flag requires 0.0.0.0.
🪄 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: 72db8f4e-8ae4-4108-9e19-acef5662f5bf

📥 Commits

Reviewing files that changed from the base of the PR and between ba19399 and 946e5bb.

📒 Files selected for processing (6)
  • bin/lib/local-inference.js
  • bin/lib/onboard.js
  • scripts/setup.sh
  • spark-install.md
  • test/e2e/test-gpu-e2e.sh
  • test/local-inference.test.js
✅ Files skipped from review due to trivial changes (2)
  • test/e2e/test-gpu-e2e.sh
  • spark-install.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/setup.sh

Comment on lines +101 to +103
process.platform === "darwin"
? "Local Ollama is responding on localhost, but containers cannot reach http://host.openshell.internal:11434. Restart Docker Desktop and ensure host networking is enabled."
: "Local Ollama is responding on localhost, but containers cannot reach http://host.openshell.internal:11434. Ensure Ollama listens on 0.0.0.0:11434 (not 127.0.0.1) so sandboxes can reach it via the Docker bridge.",
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

WSL gets the wrong remediation here.

Line 101 sends every non-macOS host down the 0.0.0.0 guidance, but bin/lib/onboard.js Lines 2645-2651 intentionally skip any OLLAMA_HOST override on WSL. If container reachability fails there, this message tells WSL users to expose Ollama unnecessarily instead of troubleshooting the Docker/WSL path. Please add a WSL-specific branch, or pass the actual startup mode into validateLocalProvider, so the guidance matches how Ollama was launched.

Comment on lines +2645 to +2650
let ollamaEnv = "";
if (!isWsl()) {
ollamaEnv =
process.platform === "darwin"
? "OLLAMA_HOST=127.0.0.1:11434 "
: "OLLAMA_HOST=0.0.0.0:11434 ";
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

Non-WSL Linux still publishes Ollama off-host.

Line 2650 keeps the default Linux launch path on OLLAMA_HOST=0.0.0.0:11434. A normal nemoclaw onboard on Linux therefore still exposes the Ollama API beyond the host, so this hardening only lands for macOS right now. If Linux is meant to be covered too, this branch needs to stop forcing 0.0.0.0.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/onboard.js` around lines 2645 - 2650, The code sets ollamaEnv to
"OLLAMA_HOST=0.0.0.0:11434" for non-WSL Linux which exposes the API off-host;
change the non-WSL branch that currently checks process.platform to use a
loopback bind (e.g., "OLLAMA_HOST=127.0.0.1:11434") instead of 0.0.0.0 so Linux
gets the same hardening as macOS; update the ollamaEnv assignment (the variable
ollamaEnv and the surrounding isWsl() / process.platform logic) to default to
127.0.0.1 unless an explicit configuration/flag requires 0.0.0.0.

Resolved conflicts:
- bin/lib/local-inference.js: take main's dist/ shim (implementation
  moved to src/lib/local-inference.ts)
- bin/lib/onboard.js: keep PR's platform-aware Ollama binding
  (127.0.0.1 on macOS, 0.0.0.0 on Linux, WSL2 default) for
  install-ollama; add main's new vllm handler block
- src/lib/local-inference.ts: update container reachability error
  message to be platform-aware (mirrors new onboard.js binding logic)
- src/lib/local-inference.test.ts: update test to match platform-aware
  error message
- test/e2e/test-gpu-e2e.sh: keep main's NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE
  check; update comment to clarify Linux-only 0.0.0.0 requirement
- scripts/setup.sh, test/local-inference.test.js: accept main's
  deletion (setup.sh superseded; test moved to TypeScript)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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

🤖 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 2751-2764: The Ollama bind-selection (the computation of ollamaEnv
using isWsl() and process.platform === "darwin") must be reused for both launch
paths so macOS doesn't get OLLAMA_HOST=0.0.0.0:11434; update the code that runs
Ollama (the run(...) call in the non-install branch where selected.key ===
"ollama") to compute and use the same ollamaEnv logic (or call a small helper
function) as the install-ollama path instead of hardcoding 0.0.0.0, referencing
the existing isWsl, ollamaEnv variable logic and the run(...) invocation to
locate where to change.

In `@src/lib/local-inference.ts`:
- Around line 122-124: The current platform branch uses only darwin vs else and
incorrectly directs WSL users to Linux advice; update the conditional that
checks process.platform (the ternary producing the two hint strings) to detect
WSL (e.g., check process.env.WSL_DISTRO_NAME or process.platform === "linux" &&
/microsoft/i.test(require("os").release())) and add a third branch for WSL with
a specific hint: explain that OLLAMA_HOST should be left unset on WSL because
0.0.0.0 breaks host-gateway reachability and point them to restart Docker
Desktop or use appropriate WSL host networking workarounds (mirroring the intent
in bin/lib/onboard.js). Ensure the darwin and non-WSL linux messages remain
unchanged.
🪄 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: 0b808fec-4392-4e0b-9cc2-c4cdc6567bb1

📥 Commits

Reviewing files that changed from the base of the PR and between 946e5bb and 65e8570.

📒 Files selected for processing (5)
  • bin/lib/onboard.js
  • spark-install.md
  • src/lib/local-inference.test.ts
  • src/lib/local-inference.ts
  • test/e2e/test-gpu-e2e.sh
✅ Files skipped from review due to trivial changes (3)
  • spark-install.md
  • src/lib/local-inference.test.ts
  • test/e2e/test-gpu-e2e.sh

Comment on lines +2751 to +2764
// On macOS, Docker Desktop routes host-gateway through the VM so
// 127.0.0.1 is reachable from containers — bind to localhost to
// avoid exposing Ollama to the LAN (CWE-668, NVBUG 6014821).
// On Linux, containers access the host via the Docker bridge IP
// so 0.0.0.0 is required for reachability.
// On WSL2, the default binding works without override.
let ollamaEnv = "";
if (!isWsl()) {
ollamaEnv =
process.platform === "darwin"
? "OLLAMA_HOST=127.0.0.1:11434 "
: "OLLAMA_HOST=0.0.0.0:11434 ";
}
run(`${ollamaEnv}ollama serve > /dev/null 2>&1 &`, { ignoreError: true });
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

Reuse the bind-selection logic in both Ollama launch paths.

Line 2334 makes install-ollama macOS-only, so the non-darwin branch here is dead. Meanwhile Line 2697 in the regular selected.key === "ollama" flow still launches a stopped Ollama with OLLAMA_HOST=0.0.0.0:11434 on macOS, which reintroduces the LAN exposure this PR is trying to remove.

💡 Suggested fix
+function getOllamaServeEnvPrefix() {
+  if (isWsl()) return "";
+  return process.platform === "darwin"
+    ? "OLLAMA_HOST=127.0.0.1:11434 "
+    : "OLLAMA_HOST=0.0.0.0:11434 ";
+}
...
-          const ollamaEnv = isWsl() ? "" : "OLLAMA_HOST=0.0.0.0:11434 ";
+          const ollamaEnv = getOllamaServeEnvPrefix();
           run(`${ollamaEnv}ollama serve > /dev/null 2>&1 &`, { ignoreError: true });
...
-        let ollamaEnv = "";
-        if (!isWsl()) {
-          ollamaEnv =
-            process.platform === "darwin"
-              ? "OLLAMA_HOST=127.0.0.1:11434 "
-              : "OLLAMA_HOST=0.0.0.0:11434 ";
-        }
+        const ollamaEnv = getOllamaServeEnvPrefix();
         run(`${ollamaEnv}ollama serve > /dev/null 2>&1 &`, { ignoreError: true });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/onboard.js` around lines 2751 - 2764, The Ollama bind-selection (the
computation of ollamaEnv using isWsl() and process.platform === "darwin") must
be reused for both launch paths so macOS doesn't get OLLAMA_HOST=0.0.0.0:11434;
update the code that runs Ollama (the run(...) call in the non-install branch
where selected.key === "ollama") to compute and use the same ollamaEnv logic (or
call a small helper function) as the install-ollama path instead of hardcoding
0.0.0.0, referencing the existing isWsl, ollamaEnv variable logic and the
run(...) invocation to locate where to change.

Comment on lines +122 to +124
process.platform === "darwin"
? "Local Ollama is responding on localhost, but containers cannot reach http://host.openshell.internal:11434. Restart Docker Desktop and ensure host networking is enabled."
: "Local Ollama is responding on localhost, but containers cannot reach http://host.openshell.internal:11434. Ensure Ollama listens on 0.0.0.0:11434 (not 127.0.0.1) so sandboxes can reach it via the Docker bridge.",
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

Handle WSL separately in the Ollama reachability hint.

This darwin/else split still sends WSL users to the Linux advice, but bin/lib/onboard.js intentionally leaves OLLAMA_HOST unset on WSL because 0.0.0.0 breaks host-gateway reachability there. If this validation fails on WSL, the message now points users at the wrong remediation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/local-inference.ts` around lines 122 - 124, The current platform
branch uses only darwin vs else and incorrectly directs WSL users to Linux
advice; update the conditional that checks process.platform (the ternary
producing the two hint strings) to detect WSL (e.g., check
process.env.WSL_DISTRO_NAME or process.platform === "linux" &&
/microsoft/i.test(require("os").release())) and add a third branch for WSL with
a specific hint: explain that OLLAMA_HOST should be left unset on WSL because
0.0.0.0 breaks host-gateway reachability and point them to restart Docker
Desktop or use appropriate WSL host networking workarounds (mirroring the intent
in bin/lib/onboard.js). Ensure the darwin and non-WSL linux messages remain
unchanged.

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

Labels

Local Models Running NemoClaw with local models security Something isn't secure status: needs-info For issues/PRs that lack a description. (Signals to the author that more detail is required).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants