fix: add missing 0.0.0.0/8 and ::/128 CIDR blocks to MCPSecurityPolicy#6907
fix: add missing 0.0.0.0/8 and ::/128 CIDR blocks to MCPSecurityPolicy#6907jongio merged 5 commits intoAzure:mainfrom
Conversation
Add 0.0.0.0/8 and ::/128 to BlockPrivateNetworks() to prevent SSRF via: - 0.0.0.0/8 'this' network (reaches loopback on Linux/macOS) - ::/128 IPv6 unspecified address (reaches loopback) Also add comments to all CIDR entries and extend tests with IPv6 coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates the MCP SSRF security policy to ensure additional “special” IP ranges are treated as private/blocked, aligning behavior with the original azd-rest implementation.
Changes:
- Add
0.0.0.0/8(“this” network) and::/128(IPv6 unspecified) toMCPSecurityPolicy.BlockPrivateNetworks(). - Extend unit tests to assert these addresses (and related IPv6 literals) are blocked by
CheckURL.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| cli/azd/pkg/azdext/mcp_security.go | Expands the private-network CIDR denylist to cover 0.0.0.0/8 and ::/128 for SSRF hardening. |
| cli/azd/pkg/azdext/mcp_security_test.go | Adds test cases confirming the new CIDRs (and IPv6 literals) are rejected by the policy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add fc00::/7 (IPv6 unique local addresses, RFC 4193) to BlockPrivateNetworks() This is the IPv6 equivalent of RFC 1918 that was missing entirely. - Add defense-in-depth using net.IP built-in methods (IsLoopback, IsPrivate, IsLinkLocalUnicast, IsUnspecified) to catch encoding variants that evade CIDR length matching. - Handle deprecated IPv4-compatible IPv6 addresses (::x.x.x.x) by extracting the embedded IPv4 and re-checking against all CIDRs and built-in methods. - Add test cases for fd00::1, fd12:3456:789a::1, ::127.0.0.1, ::10.0.0.1. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add missing CIDRs: CGNAT (100.64.0.0/10), 6to4 (2002::/16), Teredo (2001::/32), NAT64 (64:ff9b::/96, 64:ff9b:1::/48) - Add IPv4-compatible and IPv4-translated IPv6 address extraction to prevent encoding-based CIDR bypass - Add URL scheme allowlist: reject all schemes except http/https (closes ftp/gopher/ws/file/protocol-relative bypasses) - Add sync.RWMutex to MCPSecurityPolicy for concurrent safety - Add tests for exotic scheme blocking and IPv6 encoding variants Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Carrier-Grade NAT (CGNAT/RFC 6598) is used in mcp_security.go comments to describe the 100.64.0.0/10 CIDR block. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
1 similar comment
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
Summary
Hardens
BlockPrivateNetworks()inpkg/azdext/mcp_security.gowith three classes of fixes found during MQ security audit:1. Missing CIDRs (HIGH — CWE-918, CVSS 7.2)
0.0.0.0/8::/128::1)fc00::/7Without
fc00::/7, a URL likehttp://[fd12:3456:789a::1]:8080/internalbypasses all private network checks. This is the IPv6 equivalent of10.0.0.0/8being missing.2. Defense-in-depth via net.IP built-in methods (MEDIUM)
Added
IsLoopback(),IsPrivate(),IsLinkLocalUnicast(),IsUnspecified()checks incheckIP()as a secondary layer. These catch encoding variants that CIDR matching alone can miss due to byte-length mismatches between IPv4 and IPv6 representations.3. IPv4-compatible IPv6 bypass (MEDIUM — CWE-918, CVSS 5.3)
Deprecated IPv4-compatible IPv6 addresses (e.g.,
::127.0.0.1,::10.0.0.1) parse as 16-byte IPv6 in Go, butTo4()returns nil, causing IPv4 CIDR matches to fail due to length mismatch. Added explicit extraction of the embedded IPv4 address and re-checking against all CIDRs.Confirmed NOT exploitable
::ffff:127.0.0.1)To4()correctly converts2130706433)ParseIPreturns nil → DNS → fail-closed0177.0.0.1)%31%32%37.0.0.1)url.Parsedoesn't decode hostTests added
0.0.0.1,[::1],[::],[fe80::1],[fd00::1],[fd12:3456:789a::1],[::127.0.0.1],[::10.0.0.1]All 121 package tests pass.
Related