Skip to content

fix(security): complete SSRF blocklist with missing IANA-reserved ranges [MEDIUM]#1557

Merged
ericksoa merged 2 commits intoNVIDIA:mainfrom
Joshua-Medvinsky:fix/ssrf-blocklist-completeness
Apr 11, 2026
Merged

fix(security): complete SSRF blocklist with missing IANA-reserved ranges [MEDIUM]#1557
ericksoa merged 2 commits intoNVIDIA:mainfrom
Joshua-Medvinsky:fix/ssrf-blocklist-completeness

Conversation

@Joshua-Medvinsky
Copy link
Copy Markdown
Contributor

@Joshua-Medvinsky Joshua-Medvinsky commented Apr 7, 2026

Security Finding: Incomplete SSRF Blocklist in Endpoint Validation

Severity: MEDIUM
Reported by: FailSafe Security Researcher
Component: nemoclaw/src/blueprint/ssrf.tsPRIVATE_NETWORKS blocklist

Description

The isPrivateIp() function in the SSRF protection module maintains a hardcoded blocklist of private IP ranges used to prevent the sandbox from connecting to internal network services. The blocklist is missing several reserved address ranges defined by IANA, allowing an attacker to route requests to internal infrastructure through addresses that bypass the filter.

Missing ranges:

  • 0.0.0.0/8 — "This network" (RFC 1122). On many systems, 0.0.0.0 resolves to localhost, allowing the same class of attacks as 127.0.0.0/8.
  • 198.18.0.0/15 — Network benchmark testing (RFC 2544).
  • fe80::/10 — IPv6 link-local addresses. Entirely absent from the IPv6 portion of the blocklist.
  • fc00::/7 — Only fd00::/8 is blocked; the parent fc00::/7 unique local range is not fully covered.

The validateEndpointUrl() function resolves the hostname via DNS and passes each resolved address through isPrivateIp(). Any address falling in the missing ranges passes the check and is accepted as a valid endpoint URL.

Fix

  • Add 0.0.0.0/8 (RFC 1122 "this network")
  • Add 198.18.0.0/15 (RFC 2544 benchmark)
  • Add fe80::/10 (IPv6 link-local)
  • Expand fd00::/8 to fc00::/7 (full unique-local range)

Test plan

  • Verify legitimate public endpoints still pass validation
  • Verify 0.0.0.0 is now blocked
  • Verify 198.18.0.1 is now blocked
  • Verify fe80::1 is now blocked (IPv6 link-local)
  • Verify fc00::1 is now blocked (unique-local, was previously outside fd00::/8)

Summary by CodeRabbit

  • Bug Fixes
    • Improved SSRF protection by expanding blocked private/internal network ranges to include additional IPv4 ranges (notably 0.0.0.0/8 and 198.18.0.0/15), further reducing risk of unauthorized outbound requests.
  • Tests
    • Added unit tests covering the new ranges, including their IPv4-mapped IPv6 equivalents, to validate private-network blocking.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 7, 2026

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: dcdb6241-d1c8-4e34-afe2-bcf9a1e9eb00

📥 Commits

Reviewing files that changed from the base of the PR and between 8bccf50 and 0158281.

📒 Files selected for processing (2)
  • nemoclaw/src/blueprint/ssrf.test.ts
  • nemoclaw/src/blueprint/ssrf.ts

📝 Walkthrough

Walkthrough

Updated the SSRF denylist by adding two IPv4 CIDR ranges: 0.0.0.0/8 and 198.18.0.0/15. Corresponding tests were added to assert these IPv4 addresses and their IPv4-mapped IPv6 equivalents are classified as private/internal.

Changes

Cohort / File(s) Summary
SSRF CIDR Configuration
nemoclaw/src/blueprint/ssrf.ts
Added two IPv4 denylist entries: 0.0.0.0/8 and 198.18.0.0/15. No other logic or exported interfaces changed.
SSRF Tests
nemoclaw/src/blueprint/ssrf.test.ts
Extended isPrivateIp test matrix to include 0.0.0.0 and 198.18.0.1 and their IPv4-mapped IPv6 forms (::ffff:0.0.0.0, ::ffff:198.18.0.1). No other test categories were modified.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped the nets and found two spots to hide,
Marked them off with careful, tiny stride.
Tests now peek where shadows used to play,
I guard the lanes where packets stray.
🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding missing IANA-reserved IP ranges to the SSRF blocklist for enhanced security protection.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 `@nemoclaw/src/blueprint/ssrf.ts`:
- Around line 13-23: Add unit tests exercising the SSRF denylist entries defined
with cidr and cidr6: assert that addresses in 0.0.0.0/8 and 198.18.0.0/15 are
blocked, that IPv6 fe80::/10 is blocked, and that the widened fc00::/7 correctly
blocks fc00::1 while allowing fe00::1; implement these tests against the same
function used by existing tests to evaluate host/IP blocking (the SSRF denylist
checker used alongside the cidr/cidr6 definitions) so the new ranges get
explicit regression coverage.
🪄 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: ee788826-d082-46e6-a25f-7c4636909e09

📥 Commits

Reviewing files that changed from the base of the PR and between 6119baf and 6e31481.

📒 Files selected for processing (1)
  • nemoclaw/src/blueprint/ssrf.ts

@wscurran wscurran added security Something isn't secure priority: high Important issue that should be resolved in the next release fix labels Apr 8, 2026
@wscurran
Copy link
Copy Markdown
Contributor

wscurran commented Apr 8, 2026

✨ Thanks for submitting this fix, which proposes a way to strengthen SSRF protection by adding missing IANA-reserved IP ranges to the blocklist.

Copy link
Copy Markdown
Contributor

@cv cv left a comment

Choose a reason for hiding this comment

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

Security Review — WARNING (needs rebase)

The two net-new ranges are correct and should be blocked:

  • 0.0.0.0/8 (RFC 1122 "This network") — on many systems resolves to localhost
  • 198.18.0.0/15 (RFC 2544 Benchmark testing) — /15 is correct for this two-/16 block

Required change

Rebase onto current main. PR #898 already landed and added fc00::/7 and fe80::/10 to the blocklist with overlapping test coverage. After rebase:

  • Remove the now-redundant fc00::/7 and fe80::/10 additions
  • De-duplicate tests that overlap with #898's boundary tests
  • Update PR description to reflect reduced scope (two new ranges, not four)

What's good

  • CIDR notation is correct for all ranges
  • Tests cover both boundary IPs and validateEndpointUrl integration
  • No logic changes beyond the blocklist array
  • No risk of blocking legitimate traffic

…IUM]

The PRIVATE_NETWORKS blocklist was missing two IANA-reserved ranges:
- 0.0.0.0/8 ("This network", RFC 1122) — resolves to localhost on
  many systems, enabling the same class of attacks as 127.0.0.0/8
- 198.18.0.0/15 (Benchmark testing, RFC 2544) — reserved range that
  should not be reachable in production

Add both ranges and regression tests covering their boundaries and
IPv4-mapped IPv6 equivalents.

Reported-by: FailSafe Security Researcher
Co-Authored-By: Joshua Medvinsky <joshua-medvinsky@users.noreply.github.com>
@Joshua-Medvinsky Joshua-Medvinsky force-pushed the fix/ssrf-blocklist-completeness branch from 8bccf50 to 0158281 Compare April 8, 2026 23:29
@Joshua-Medvinsky
Copy link
Copy Markdown
Contributor Author

Updated per review feedback:

  • Rebased onto current main (fc00::/7, fe80::/10 already landed via test(security): add SSRF validation edge-case coverage #898)
  • Only adding the two remaining missing ranges: 0.0.0.0/8 (RFC 1122) and 198.18.0.0/15 (RFC 2544)
  • Added regression tests for both new ranges including IPv4-mapped IPv6 variants

@cv cv added the v0.0.11 Release target label Apr 9, 2026
@ericksoa ericksoa added v0.0.12 Release target and removed v0.0.11 Release target labels Apr 10, 2026
@cv cv added v0.0.13 Release target and removed v0.0.12 Release target labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

@ericksoa ericksoa left a comment

Choose a reason for hiding this comment

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

LGTM — purely additive blocklist entries for IANA-reserved ranges (0.0.0.0/8, 198.18.0.0/15). No logic changes, low regression risk.

@ericksoa ericksoa merged commit 99bd062 into NVIDIA:main Apr 11, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix priority: high Important issue that should be resolved in the next release security Something isn't secure v0.0.13 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants