Skip to content

fix(security): bind HTTPS endpoint validation to connection IP#4685

Open
1PoPTRoN wants to merge 2 commits into
NVIDIA:mainfrom
1PoPTRoN:fix/https-endpoint-dns-rebinding
Open

fix(security): bind HTTPS endpoint validation to connection IP#4685
1PoPTRoN wants to merge 2 commits into
NVIDIA:mainfrom
1PoPTRoN:fix/https-endpoint-dns-rebinding

Conversation

@1PoPTRoN
Copy link
Copy Markdown
Contributor

@1PoPTRoN 1PoPTRoN commented Jun 2, 2026

Summary

Fixes a DNS rebinding TOCTOU gap for DNS-backed HTTPS endpoints. NemoClaw now avoids handing the original hostname URL directly to the downstream provider after validation, and instead routes DNS-backed HTTPS endpoints through a local pinned proxy that connects to the validated IP while preserving TLS SNI and the Host header.

Related Issue

Fixes #4684

Changes

  • Add a local HTTPS pinning proxy for DNS-backed HTTPS inference endpoints.
  • Route validated DNS-backed HTTPS blueprint and endpoint-override URLs through the proxy instead of returning the original hostname URL.
  • Keep HTTP DNS pinning behavior unchanged.
  • Keep IP-literal HTTPS endpoints unchanged.
  • Fail closed for generic persisted config values that contain DNS-backed HTTPS URLs, since that path cannot attach SNI/Host-preserving connection pinning.
  • Update SSRF, runner, proxy, config-set tests, and troubleshooting docs.

Type of Change

  • Code change with doc updates
  • Code change (feature, bug fix, or refactor)
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Additional verification run:

  • cd nemoclaw && npm run check
  • cd nemoclaw && npm run build
  • npm run typecheck:cli
  • npx vitest run test/config-set.test.ts --config vitest.config.ts

Signed-off-by: 1PoPTRoN vrxn.arp1traj@gmail.com

Summary by CodeRabbit

  • New Features

    • Local HTTPS pinning proxy introduced to route validated HTTPS endpoints via loopback for safe connectivity.
  • Documentation

    • Troubleshooting guide expanded with detailed config URL validation rules, DNS requirements, and credential handling guidance.
  • Improvements

    • Stricter validation: DNS-backed HTTPS endpoints are rejected for persistent config (use IP literals or pinned proxies); HTTP endpoints support IP-pinning.

Copilot AI review requested due to automatic review settings June 2, 2026 21:30
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented Jun 2, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 08e02746-5fac-4098-a305-79fb32677039

📥 Commits

Reviewing files that changed from the base of the PR and between b8f38b8 and b15658f.

📒 Files selected for processing (3)
  • docs/reference/troubleshooting.mdx
  • nemoclaw/src/blueprint/https-pin-proxy.test.ts
  • nemoclaw/src/blueprint/https-pin-proxy.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/reference/troubleshooting.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • nemoclaw/src/blueprint/https-pin-proxy.test.ts
  • nemoclaw/src/blueprint/https-pin-proxy.ts

📝 Walkthrough

Walkthrough

Adds DNS-aware endpoint validation, a local loopback HTTPS pin-proxy that routes DNS-backed HTTPS to validated IPs while preserving Host/SNI, enforces stricter sandbox persistence (reject DNS-backed HTTPS), and wires proxy lifecycle into runner plus tests and docs.

Changes

HTTPS DNS Rebinding Mitigation

Layer / File(s) Summary
Documentation and troubleshooting guidance
docs/reference/troubleshooting.mdx
Expanded config set troubleshooting to describe HTTP/HTTPS URL validation, DNS resolution/pinning, and stricter rejection guidance for DNS-backed HTTPS persistence.
ValidatedEndpoint type and SSRF tests
nemoclaw/src/blueprint/ssrf.ts, nemoclaw/src/blueprint/ssrf.test.ts
Extended ValidatedEndpoint to include protocol, hostname, dnsResolved, optional resolvedAddress/resolvedFamily; updated validateEndpointUrl returns and tests to assert the richer shape for IP-literals and DNS-resolved cases.
HTTPS pinning proxy implementation and tests
nemoclaw/src/blueprint/https-pin-proxy.ts, nemoclaw/src/blueprint/https-pin-proxy.test.ts
Local loopback HTTP proxy for DNS-backed HTTPS: route model, persisted route store, request forwarding to validated IPs with original Host + SNI, hop-by-hop header sanitization, health/auth token, detached serve mode, readiness polling, and focused tests for mapping, request options, and response header sanitization.
Ports & runner wiring
nemoclaw/src/lib/ports.ts, nemoclaw/src/blueprint/runner.ts, nemoclaw/src/blueprint/runner.test.ts
Added HTTPS_PIN_PROXY_PORT; resolveRunConfig maps validated endpoints via endpointForValidatedEndpoint, collects httpsPinProxyRoutes; actionApply calls ensureHttpsPinProxyRoutes before provider setup; tests mock validation and proxy setup to assert proxy-based endpoint handling.
Sandbox config persistence rules & tests
src/lib/sandbox/config.ts, test/config-set.test.ts
DnsValidatedUrl now tracks DNS resolution state; validateUrlValueWithDnsResult returns richer shape; rewriteValidatedConfigUrl enforces: HTTP persists pinned IP form, HTTPS preserved only for IP-literals, DNS-backed HTTPS rejected for generic persistence; tests updated for rejection and pinned-IP rewriting.

Sequence Diagram(s)

sequenceDiagram
  participant Runner as runner.ts
  participant Validate as validateEndpointUrl
  participant Endpoint as endpointForValidatedEndpoint
  participant Proxy as ensureHttpsPinProxyRoutes
  participant Inference as Inference Provider
  Runner->>Validate: Validate endpoint URL
  Validate->>Validate: Resolve DNS (if hostname)
  Validate-->>Runner: Return ValidatedEndpoint with resolved IP
  Runner->>Endpoint: Map validated endpoint
  Endpoint->>Endpoint: Determine if DNS-backed HTTPS
  Endpoint-->>Runner: Return endpoint + optional proxy route
  Runner->>Proxy: Setup proxy if route generated
  Proxy->>Proxy: Spawn local HTTP proxy process
  Proxy->>Proxy: Register routes with resolved IPs
  Proxy-->>Runner: Proxy ready on loopback
  Runner->>Inference: Configure with proxy URL or pinned URL
Loading
sequenceDiagram
  participant Client as Blueprint/Provider
  participant ProxyServer as Local HTTP Proxy
  participant Upstream as Upstream HTTPS Endpoint
  Client->>ProxyServer: GET /https-pin/<route-id>/...
  ProxyServer->>ProxyServer: Load route by id and verify resolved IP
  ProxyServer->>Upstream: https.request to validated IP with Host + SNI = original hostname
  Upstream->>ProxyServer: TLS handshake + response
  ProxyServer->>Client: Stream proxied response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

fix, NemoClaw CLI, documentation, v0.0.57

Suggested reviewers

  • cv
  • prekshivyas
  • ericksoa

Poem

🐇 I poked a hole through DNS fog,
Pinned the host and kept the log,
Loopback tunnels hum and hop,
TLS stays true — no sly flip-flop.
— your friendly rabbit, hopping secure

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.35% 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 title accurately summarizes the main security fix: binding HTTPS endpoint validation to the connection IP to prevent DNS rebinding attacks.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #4684 by implementing HTTPS pinning proxy routing, DNS validation binding, and stricter HTTPS handling with closed-failure semantics.
Out of Scope Changes check ✅ Passed All changes are directly aligned with fixing the DNS rebinding TOCTOU vulnerability and supporting infrastructure for HTTPS endpoint validation binding.

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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR tightens SSRF/DNS-rebinding safety around persisted HTTPS URLs by rejecting DNS-backed HTTPS endpoints in generic config persistence and introducing an HTTPS pinning proxy for blueprint runs that preserves TLS SNI/HTTP Host while pinning the connection IP.

Changes:

  • Reject DNS-backed HTTPS URLs during config set persistence (while still pinning HTTP and allowing HTTPS IP-literals).
  • Extend SSRF validation results with protocol/hostname/DNS-resolution metadata and use it to route DNS-backed HTTPS endpoints through a local pinning proxy.
  • Add the HTTPS pinning proxy implementation, port configuration, tests, and troubleshooting docs.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/config-set.test.ts Updates expectations to reject DNS-backed HTTPS persistence and to use IP-literal HTTPS where allowed.
src/lib/sandbox/config.ts Tracks DNS resolution details and rejects DNS-backed HTTPS URLs on persistence with a clearer error path.
nemoclaw/src/lib/ports.ts Adds a dedicated env-configurable port for the HTTPS pin proxy.
nemoclaw/src/blueprint/ssrf.ts Expands validated endpoint output to include DNS/pinning metadata needed by the proxy routing logic.
nemoclaw/src/blueprint/ssrf.test.ts Adds assertions for new SSRF metadata fields and DNS-resolved behavior.
nemoclaw/src/blueprint/runner.ts Routes DNS-backed HTTPS endpoints through the pin proxy and ensures routes exist during apply.
nemoclaw/src/blueprint/runner.test.ts Adds tests for proxy routing behavior and for starting/ensuring proxy routes on apply.
nemoclaw/src/blueprint/https-pin-proxy.ts Introduces the HTTPS pinning proxy server, persistence, routing, and spawn/health logic.
nemoclaw/src/blueprint/https-pin-proxy.test.ts Tests endpoint routing and request option construction (SNI/Host preservation + IP pin).
docs/reference/troubleshooting.mdx Documents the new behavior/error guidance for DNS-backed HTTPS in config persistence.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread nemoclaw/src/blueprint/https-pin-proxy.ts
Comment thread nemoclaw/src/blueprint/https-pin-proxy.ts
Comment thread nemoclaw/src/blueprint/https-pin-proxy.ts
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)
src/lib/sandbox/config.ts (1)

836-838: 💤 Low value

Per coding guidelines, consider running E2E tests for this config persistence change.

This change modifies URL persistence rules in config set. As per the coding guidelines for this file, changes to config writes affect Docker/VM sandboxes and should be validated with E2E tests.

gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=shields-config-e2e
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/sandbox/config.ts` around lines 836 - 838, This change updates URL
persistence rules around the "Validate URLs for SSRF" block in
src/lib/sandbox/config.ts (affecting the config set path), so run the nightly
E2E job for config persistence to validate behavior in Docker/VM sandboxes:
execute the GitHub Actions workflow with gh workflow run nightly-e2e.yaml --ref
<branch> -f jobs=shields-config-e2e and verify tests for config
writes/pass-through of HTTP vs HTTPS URL pinning pass; if failures occur, adjust
the config set logic around the URL persistence code until the E2E passes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/reference/troubleshooting.mdx`:
- Line 833: The long single source line beginning "Host-side `config set`
validates any HTTP or HTTPS URLs..." should be split so each sentence is on its
own source line; locate the paragraph starting with that text and break it into
separate lines at each sentence boundary, preserving punctuation, inline code
formatting (backticks), and original wording (including the clause about
loopback/private/reserved/internal hosts, DNS resolution and IP pinning, the
HTTPS/Host/SNI note, and the credential-rotation recommendation) to improve diff
readability.

In `@nemoclaw/src/blueprint/https-pin-proxy.ts`:
- Around line 263-284: The upstream HTTPS request created by https.request
(assigned to upstream from buildPinnedHttpsRequestOptions) lacks a timeout and
can hang; add a request timeout (e.g., 30s) by calling
upstream.setTimeout(timeoutMs) and listen for the 'timeout' event to destroy the
upstream socket with an Error, then mirror the existing error handling: if
!res.headersSent call sendError(res, 502, "...timeout...") else
res.destroy(err); ensure you also handle cleanup when upstream emits 'close' or
'error' and keep the existing req.pipe(upstream) flow.

---

Nitpick comments:
In `@src/lib/sandbox/config.ts`:
- Around line 836-838: This change updates URL persistence rules around the
"Validate URLs for SSRF" block in src/lib/sandbox/config.ts (affecting the
config set path), so run the nightly E2E job for config persistence to validate
behavior in Docker/VM sandboxes: execute the GitHub Actions workflow with gh
workflow run nightly-e2e.yaml --ref <branch> -f jobs=shields-config-e2e and
verify tests for config writes/pass-through of HTTP vs HTTPS URL pinning pass;
if failures occur, adjust the config set logic around the URL persistence code
until the E2E passes.
🪄 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: Enterprise

Run ID: 9b8f9cd5-848f-4c13-b660-61bccddd0106

📥 Commits

Reviewing files that changed from the base of the PR and between 3f8e401 and b8f38b8.

📒 Files selected for processing (10)
  • docs/reference/troubleshooting.mdx
  • nemoclaw/src/blueprint/https-pin-proxy.test.ts
  • nemoclaw/src/blueprint/https-pin-proxy.ts
  • nemoclaw/src/blueprint/runner.test.ts
  • nemoclaw/src/blueprint/runner.ts
  • nemoclaw/src/blueprint/ssrf.test.ts
  • nemoclaw/src/blueprint/ssrf.ts
  • nemoclaw/src/lib/ports.ts
  • src/lib/sandbox/config.ts
  • test/config-set.test.ts

Comment thread docs/reference/troubleshooting.mdx Outdated
Comment thread nemoclaw/src/blueprint/https-pin-proxy.ts
@wscurran wscurran added area: inference Inference routing, serving, model selection, or outputs area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression labels Jun 3, 2026
@wscurran
Copy link
Copy Markdown
Contributor

wscurran commented Jun 3, 2026

✨ Thanks for submitting this detailed PR about fixing a DNS rebinding TOCTOU gap for DNS-backed HTTPS endpoints. This proposes a way to enhance the security of NemoClaw's inference endpoints.


Related open issues:

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

Labels

area: inference Inference routing, serving, model selection, or outputs area: security Security controls, permissions, secrets, or hardening bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DNS rebinding TOCTOU for HTTPS endpoint validation

3 participants