From 4f4f0697326ba6758cf17ec2e244e72893a1b44e Mon Sep 17 00:00:00 2001 From: Dan Lorenc Date: Thu, 30 Nov 2023 14:15:32 -0500 Subject: [PATCH] Limit ReDOS by checking the length before running the regexp. Go doesn't support look-ahead assertions so I did this out of the regexp. Signed-off-by: Dan Lorenc --- urls.go | 6 ++++++ urls_test.go | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/urls.go b/urls.go index 01f179f..70e9a5c 100644 --- a/urls.go +++ b/urls.go @@ -30,6 +30,9 @@ import ( "strings" ) +// Max length of the scpUrl to prevent reDOS attacks +const maxLen = 1000 + var ( // scpSyntax was modified from https://golang.org/src/cmd/go/vcs.go. scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9-._~]+@)?([a-zA-Z0-9._-]+):([a-zA-Z0-9./._-]+)(?:\?||$)(.*)$`) @@ -90,6 +93,9 @@ func ParseTransport(rawurl string) (*url.URL, error) { // ParseScp parses rawurl into a URL object. The rawurl must be // an SCP-like URL, otherwise ParseScp returns an error. func ParseScp(rawurl string) (*url.URL, error) { + if len(rawurl) > maxLen { + return nil, fmt.Errorf("URL too long: %q", rawurl) + } match := scpSyntax.FindAllStringSubmatch(rawurl, -1) if len(match) == 0 { return nil, fmt.Errorf("no scp URL found in %q", rawurl) diff --git a/urls_test.go b/urls_test.go index d4f1f72..f882add 100644 --- a/urls_test.go +++ b/urls_test.go @@ -218,3 +218,11 @@ func TestParse(t *testing.T) { } } } + +func TestTooLong(t *testing.T) { + longUrl := "https://example.com/" + strings.Repeat("a", 2048) + _, err := ParseScp(longUrl) + if err == nil { + t.Errorf("Parse(%q) = nil, want error", longUrl) + } +}