Refuse [::], 0.0.0.0, IPv6 multicast and documentation space (closes #341)
check / check (push) Waiting to run
check / check (push) Waiting to run
On the build host a connection to [::] reaches a listener on ::1, and one to 0.0.0.0 reaches 127.0.0.1, so a delivery target at either reached this host's loopback past the guard. 0.0.0.0/32 and ::/128 are now in alwaysBlockedNetworks, which no allowlist opens; an allowlist reaches loopback only through an entry covering a loopback address. IPv6 multicast (ff00::/8) and documentation space (2001:db8::/32) are refused by default and reopen when listed. Every default blocklist entry has a one-line comment, each list is pinned on its own, and tests refuse each address at target creation and at delivery. The README and the rules above each list match. Model: opus-5-5
This commit was merged in pull request #422.
This commit is contained in:
@@ -168,12 +168,13 @@ func TestGuardAllowlist_UnlistedPrivateStillRefused(t *testing.T) {
|
||||
|
||||
// TestGuardAllowlist_MetadataAlwaysRefused is the load-bearing
|
||||
// case: cloud instance metadata endpoints are credential theft
|
||||
// rather than delivery to an internal service, so no allowlist
|
||||
// reaches one. Every guard below names a CIDR that covers its
|
||||
// target — including 0.0.0.0/0, ::/0, and the ordinary ULA and
|
||||
// CGNAT blocks an operator would really list — and the address
|
||||
// must stay refused anyway, on both the validation and the
|
||||
// delivery path.
|
||||
// rather than delivery to an internal service, and the
|
||||
// unspecified addresses 0.0.0.0 and :: reach this host's loopback
|
||||
// on Linux, so no allowlist reaches any of them. Every guard
|
||||
// below names a CIDR that covers its target — including
|
||||
// 0.0.0.0/0, ::/0, and the ordinary ULA and CGNAT blocks an
|
||||
// operator would really list — and the address must stay
|
||||
// refused anyway, on both the validation and the delivery path.
|
||||
func TestGuardAllowlist_MetadataAlwaysRefused(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -219,15 +220,17 @@ type metadataAlwaysRefusedCase struct {
|
||||
}
|
||||
|
||||
// metadataAlwaysRefusedCases enumerates every unconditionally
|
||||
// blocked address together with an allowlist entry that would
|
||||
// otherwise reach it. Split by family of address only to stay
|
||||
// under the function-length limit.
|
||||
// blocked address (link-local, the cloud metadata endpoints and
|
||||
// the unspecified addresses) together with an allowlist entry
|
||||
// that would otherwise reach it. Split by family of address only
|
||||
// to stay under the function-length limit.
|
||||
func metadataAlwaysRefusedCases() []metadataAlwaysRefusedCase {
|
||||
cases := linkLocalRefusedCases()
|
||||
cases = append(cases, ulaMetadataRefusedCases()...)
|
||||
cases = append(cases, ipv4MetadataRefusedCases()...)
|
||||
cases = append(cases, encodedMetadataRefusedCases()...)
|
||||
|
||||
return append(cases, encodedMetadataRefusedCases()...)
|
||||
return append(cases, unspecifiedRefusedCases()...)
|
||||
}
|
||||
|
||||
// linkLocalRefusedCases covers the link-local blocks, including
|
||||
@@ -367,6 +370,23 @@ func encodedMetadataRefusedCases() []metadataAlwaysRefusedCase {
|
||||
}
|
||||
}
|
||||
|
||||
// unspecifiedRefusedCases covers the unspecified addresses, each
|
||||
// of which reaches this host's loopback on Linux.
|
||||
func unspecifiedRefusedCases() []metadataAlwaysRefusedCase {
|
||||
return []metadataAlwaysRefusedCase{
|
||||
{
|
||||
name: "IPv4 unspecified address under 0.0.0.0/0",
|
||||
allow: allowAllIPv4,
|
||||
target: "http://0.0.0.0:8080/hook",
|
||||
},
|
||||
{
|
||||
name: "IPv6 unspecified address under ::/0",
|
||||
allow: allowAllIPv6,
|
||||
target: "http://[::]:8080/hook",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestGuardAllowlist_PublicUnaffected asserts the allowlist does
|
||||
// not narrow anything: public addresses were reachable before it
|
||||
// existed and stay reachable, whether or not a list is set.
|
||||
@@ -524,6 +544,10 @@ func TestAlwaysBlockedNetworks_PinnedSet(t *testing.T) {
|
||||
// Oracle Cloud Classic metadata, inside the blocked
|
||||
// 192.0.0.0/24.
|
||||
"192.0.0.192/32",
|
||||
// The IPv4 and IPv6 unspecified addresses, each of
|
||||
// which reaches this host's loopback on Linux.
|
||||
"0.0.0.0/32",
|
||||
"::/128",
|
||||
// 169.254.169.254 as an IPv4-compatible IPv6 address.
|
||||
"::a9fe:a9fe/128",
|
||||
// 169.254.169.254 behind the NAT64 well-known prefix.
|
||||
@@ -556,7 +580,8 @@ func TestDefaultBlocklist_PinnedSet(t *testing.T) {
|
||||
{cidr: "172.16.0.0/12", reopenable: true},
|
||||
{cidr: "192.168.0.0/16", reopenable: true},
|
||||
{cidr: linkLocalIPv4, reopenable: false},
|
||||
{cidr: "0.0.0.0/8", reopenable: true},
|
||||
// Its first address, 0.0.0.0, is in the unconditional set.
|
||||
{cidr: "0.0.0.0/8", reopenable: false},
|
||||
{cidr: "100.64.0.0/10", reopenable: true},
|
||||
{cidr: "192.0.0.0/24", reopenable: true},
|
||||
{cidr: "192.0.2.0/24", reopenable: true},
|
||||
@@ -566,8 +591,11 @@ func TestDefaultBlocklist_PinnedSet(t *testing.T) {
|
||||
{cidr: "224.0.0.0/4", reopenable: true},
|
||||
{cidr: "240.0.0.0/4", reopenable: true},
|
||||
{cidr: "::1/128", reopenable: true},
|
||||
{cidr: "::/128", reopenable: false},
|
||||
{cidr: "fc00::/7", reopenable: true},
|
||||
{cidr: "fe80::/10", reopenable: false},
|
||||
{cidr: "ff00::/8", reopenable: true},
|
||||
{cidr: "2001:db8::/32", reopenable: true},
|
||||
{cidr: "168.63.129.16/32", public: true, reopenable: true},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user