• v1.7.7 f5f40bd980

    Ghost released this 2026-05-04 09:41:23 -04:00 | 111 commits to main since this release

    The HTTP namespace-verification fetcher's isBlockedIP composed its
    blocklist from Go stdlib's Is* helpers plus a manual CGNAT range. That
    covers IPv4 cloud metadata, RFC1918, ULA, and link-local — but Go's
    classification helpers don't recognise IPv6 prefix families that embed
    or tunnel to arbitrary IPv4:

    • 2002::/16 RFC 3056 6to4 — bits 16-47 are an arbitrary IPv4
    • 64:ff9b::/96 RFC 6052 NAT64 well-known — low 32 bits are IPv4
    • 64:ff9b:1::/48 RFC 8215 NAT64 local-use — same IPv4-embedding shape
    • fec0::/10 RFC 3879 site-local (deprecated, still routed by
      some stacks)

    On hosts with 6to4 routing or a NAT64 next-hop (the default on
    IPv6-only GKE node pools, AWS IPv6-only EC2, Azure IPv6 VMs with
    NAT64, and many corporate DNS64/NAT64 networks), an attacker who
    controls DNS for a publisher domain can cause the registry to dial
    169.254.169.254, 10.0.0.0/8, etc. via the IPv6 wrapper. Same
    SSRF class as GHSA-56c3-vfp2-5qqj on n8n-mcp.

    Define the four prefixes via a new mustCIDR helper (panic on
    malformed CIDR at init so a typo can't fail-open silently) and iterate
    them in isBlockedIP after the stdlib gates. Refactor the existing
    CGNAT IIFE to use the same helper for consistency. IPv4-mapped IPv6
    (::ffff:0:0/96) needs no special-casing: Go's Is* helpers honour the
    To4() fast-path, so e.g. ::ffff:10.0.0.1 is already classified as
    IsPrivate.

    Adds 17 test cases to TestIsBlockedIP covering each new prefix
    family, IPv4-mapped IPv6 sanity checks, and just-outside-the-range
    positive controls (2001::1, 2003::1, 64:ff9c::1).

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

    Downloads