Refuse an IPv6 address that holds an internal IPv4 address (closes #297)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
The check that keeps pixa from fetching internal addresses read an IPv6 address as IPv4 only in the mapped form (::ffff:a.b.c.d), so the IPv4-compatible form, such as ::127.0.0.1, was judged as IPv6 and passed. An address in ::/96 is now judged by the IPv4 address it holds, so one holding a private, loopback or link-local address is refused on both image routes before any upstream request. The NAT64 range 64:ff9b::/96 stays blocked whole, as it was on next. Model: opus-5-5
This commit was merged in pull request #298.
This commit is contained in:
@@ -543,6 +543,13 @@ func isPrivateIP(ip net.IP) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// An IPv4-compatible IPv6 address (in ::/96, such as ::127.0.0.1) holds
|
||||
// an IPv4 address in its last four bytes and is judged as that address
|
||||
if addr, ok := netip.AddrFromSlice(ip); ok &&
|
||||
netip.MustParsePrefix("::/96").Contains(addr) {
|
||||
return isPrivateIP(ip[12:])
|
||||
}
|
||||
|
||||
// Check for loopback
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
|
||||
@@ -186,6 +186,44 @@ func TestIsPrivateIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsPrivateIPJudgesEmbeddedIPv4Address checks IPv6 addresses that hold an
|
||||
// IPv4 address in their last four bytes: the IPv4-compatible form (::/96) and
|
||||
// the NAT64 form (64:ff9b::/96). One holding a loopback, private or
|
||||
// link-local IPv4 address is refused as that address is, and one holding a
|
||||
// public IPv4 address in the IPv4-compatible form passes.
|
||||
func TestIsPrivateIPJudgesEmbeddedIPv4Address(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
ip string
|
||||
want bool
|
||||
}{
|
||||
{"::127.0.0.1", true}, // loopback
|
||||
{"::10.0.0.1", true}, // private
|
||||
{"::169.254.169.254", true}, // link-local
|
||||
{"64:ff9b::7f00:1", true}, // NAT64 form of 127.0.0.1
|
||||
{"::8.8.8.8", false}, // public
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.ip, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ip := net.ParseIP(tc.ip)
|
||||
if ip == nil {
|
||||
t.Fatalf("failed to parse IP %q", tc.ip)
|
||||
}
|
||||
|
||||
got := isPrivateIP(ip)
|
||||
t.Logf("isPrivateIP(%s) = %v", ip, got)
|
||||
|
||||
if got != tc.want {
|
||||
t.Errorf("isPrivateIP(%q) = %v, want %v", tc.ip, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateURL_RejectsNonHTTPS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user