package guard // P6 (owner, before the run): PreCheck is CheckURL without name resolution, for refusing a batch target at // submit time. import ( "context" "net/netip" "strings" "testing" ) func TestPreCheck(t *testing.T) { g := &Guard{ AllowPrefixes: []netip.Prefix{netip.MustParsePrefix("127.0.0.0/8")}, LookupIP: func(context.Context, string) ([]netip.Addr, error) { t.Fatal("PreCheck resolved a name") return nil, nil }, } for _, u := range []string{ "https://example.com/", "http://example.com/path?q=1", "https://internal.test/", // a name: not resolved here, so not refused here "http://127.0.0.1:8080/", // an allowed literal is exempt from the port rule, as in CheckURL "http://93.184.215.14/", // a public literal "http://0x7f000001:8080/", // inet_aton form of 127.0.0.1: an allowed literal } { if err := g.PreCheck(u); err != nil { t.Errorf("PreCheck(%q) = %v, want nil", u, err) } } for _, u := range []string{ "", "ftp://example.com/", "http://user@example.com/", "http://example.com:8080/", "http://10.0.0.5/", "http://169.254.169.254/latest/meta-data/", "http://[::1]/", "http://0x0a000005/", // inet_aton form of 10.0.0.5 } { err := g.PreCheck(u) if err == nil || !strings.HasPrefix(err.Error(), "blocked") { t.Errorf("PreCheck(%q) = %v, want a blocked error", u, err) } } // With no allow list, loopback is refused like any other private literal. var zero Guard if err := zero.PreCheck("http://127.0.0.1/"); err == nil { t.Error("a zero Guard allowed loopback") } }