From 67b160e46610d7995fcb2ad64e4181cbd31b1d15 Mon Sep 17 00:00:00 2001 From: Artem Date: Sat, 2 Apr 2022 20:29:47 +0300 Subject: [PATCH] Fix: validate URI --- cmd/metadata/resolver/http.go | 41 +++++++++++++++++++++++++- cmd/metadata/resolver/http_test.go | 47 ++++++++++++++++++++++++++++++ cmd/metadata/resolver/resolver.go | 4 +++ cmd/metadata/token.go | 4 +++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 cmd/metadata/resolver/http_test.go diff --git a/cmd/metadata/resolver/http.go b/cmd/metadata/resolver/http.go index 50d0c8e..19aba6b 100644 --- a/cmd/metadata/resolver/http.go +++ b/cmd/metadata/resolver/http.go @@ -2,8 +2,10 @@ package resolver import ( "context" + "fmt" "io" "io/ioutil" + "net" "net/http" "net/url" "strings" @@ -61,10 +63,15 @@ func NewHttp(opts ...HttpOption) Http { // Resolve - func (s Http) Resolve(ctx context.Context, network, address, link string) ([]byte, error) { - if _, err := url.ParseRequestURI(link); err != nil { + parsed, err := url.ParseRequestURI(link) + if err != nil { return nil, ErrInvalidURI } + if err := s.ValidateURL(parsed); err != nil { + return nil, err + } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, link, nil) if err != nil { return nil, err @@ -92,3 +99,35 @@ func (s Http) Resolve(ctx context.Context, network, address, link string) ([]byt func (s Http) Is(link string) bool { return strings.HasPrefix(link, prefixHttp) || strings.HasPrefix(link, prefixHttps) } + +// ValidateURL - +func (s Http) ValidateURL(link *url.URL) error { + if link.Host == "localhost" { + return errors.Wrap(ErrInvalidURI, fmt.Sprintf("invalid host: %s", link.Host)) + } + + for _, mask := range []string{ + "10.0.0.0/8", + "100.64.0.0/10", + "169.254.0.0/16", + "172.16.0.0/12", + "192.0.0.0/24", + "192.0.2.0/24", + "192.168.0.0/16", + "198.18.0.0/15", + "198.51.100.0/24", + "203.0.113.0/24", + "240.0.0.0/4", + } { + _, cidr, err := net.ParseCIDR(mask) + if err != nil { + return err + } + + ip := net.ParseIP(link.Host) + if ip != nil && cidr.Contains(ip) { + return errors.Wrap(ErrInvalidURI, fmt.Sprintf("restricted subnet: %s", mask)) + } + } + return nil +} diff --git a/cmd/metadata/resolver/http_test.go b/cmd/metadata/resolver/http_test.go new file mode 100644 index 0000000..db0ce07 --- /dev/null +++ b/cmd/metadata/resolver/http_test.go @@ -0,0 +1,47 @@ +package resolver + +import ( + "net/url" + "testing" +) + +func TestHttp_ValidateURL(t *testing.T) { + tests := []struct { + name string + link *url.URL + wantErr bool + }{ + { + name: "localhost", + link: &url.URL{ + Host: "localhost", + }, + wantErr: true, + }, { + name: "10.0.0.0/8", + link: &url.URL{ + Host: "10.0.0.1", + }, + wantErr: true, + }, { + name: "valid", + link: &url.URL{ + Host: "better-call.dev", + }, + }, { + name: "192.0.2.0/24", + link: &url.URL{ + Host: "192.0.2.1", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := Http{} + if err := s.ValidateURL(tt.link); (err != nil) != tt.wantErr { + t.Errorf("Http.ValidateURL() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/cmd/metadata/resolver/resolver.go b/cmd/metadata/resolver/resolver.go index 058f4e6..e1066ba 100644 --- a/cmd/metadata/resolver/resolver.go +++ b/cmd/metadata/resolver/resolver.go @@ -32,6 +32,7 @@ const ( ErrorTypeKeyTezosNotFond ErrorType = "tezos_key_not_found" ErrorTypeTezosURIParsing ErrorType = "tezos_uri_parsing" ErrorTypeInvalidJSON ErrorType = "invalid_json" + ErrorInvalidHTTPURI ErrorType = "invalid_http_uri" ) // ResolvingError - @@ -126,6 +127,9 @@ func (r Receiver) Resolve(ctx context.Context, network, address, link string) (r } if err != nil { + if errors.Is(err, ErrInvalidURI) { + return resolved, newResolvingError(0, ErrorInvalidHTTPURI, err) + } return } diff --git a/cmd/metadata/token.go b/cmd/metadata/token.go index 67d9892..9d1a24b 100644 --- a/cmd/metadata/token.go +++ b/cmd/metadata/token.go @@ -134,6 +134,10 @@ func (indexer *Indexer) resolveTokenMetadata(ctx context.Context, tm *models.Tok if e, ok := err.(resolver.ResolvingError); ok { indexer.incrementErrorCounter(e) err = e.Err + + if e.Type == resolver.ErrorInvalidHTTPURI { + tm.RetryCount = int8(indexer.settings.MaxRetryCountOnError) + } } if tm.RetryCount < int8(indexer.settings.MaxRetryCountOnError) {