Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions internal/cmd/curl/curl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ func TestParseInput(t *testing.T) {
model.URL = "https://www.example.website.com/"
}),
},
{
description: "hostname suffix without domain boundary",
argValues: []string{
"https://suspiciousstackit.cloud/",
},
flagValues: fixtureFlagValues(),
allowedURLDomain: "stackit.cloud",
isValid: false,
},
{
description: "invalid method 1",
argValues: fixtureArgValues(),
Expand Down
7 changes: 6 additions & 1 deletion internal/pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,13 @@ func ValidateURLDomain(value string) error {
}

allowedUrlDomain := viper.GetString(config.AllowedUrlDomainKey)
if allowedUrlDomain == "" {
return nil
}

if !strings.HasSuffix(urlHost, allowedUrlDomain) {
urlHost = strings.ToLower(urlHost)
allowedUrlDomain = strings.ToLower(allowedUrlDomain)
if urlHost != allowedUrlDomain && !strings.HasSuffix(urlHost, "."+allowedUrlDomain) {
return fmt.Errorf(`only urls belonging to domain %s are allowed`, allowedUrlDomain)
}
return nil
Expand Down
78 changes: 78 additions & 0 deletions internal/pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,60 @@ func TestValidateURLDomain(t *testing.T) {
input: "https://example.stackit.cloud",
isValid: true,
},
{
name: "apex domain",
allowedUrlDomain: "stackit.cloud",
input: "https://stackit.cloud/path",
isValid: true,
},
{
name: "multiple subdomains",
allowedUrlDomain: "stackit.cloud",
input: "https://dns.api.stackit.cloud/v1",
isValid: true,
},
{
name: "hostname suffix without label boundary",
allowedUrlDomain: "stackit.cloud",
input: "https://suspiciousstackit.cloud",
isValid: false,
},
{
name: "lookalike subdomain",
allowedUrlDomain: "stackit.cloud",
input: "https://api.suspiciousstackit.cloud",
isValid: false,
},
{
name: "domain followed by extra labels",
allowedUrlDomain: "stackit.cloud",
input: "https://api.stackit.cloud.evil.example",
isValid: false,
},
{
name: "port is not hostname",
allowedUrlDomain: "stackit.cloud",
input: "https://stackit.cloud:443/v1",
isValid: true,
},
{
name: "userinfo does not affect hostname",
allowedUrlDomain: "stackit.cloud",
input: "https://stackit.cloud@evil.example/path",
isValid: false,
},
{
name: "path does not affect hostname",
allowedUrlDomain: "stackit.cloud",
input: "https://evil.example/path/stackit.cloud",
isValid: false,
},
{
name: "hostname is case insensitive",
allowedUrlDomain: "stackit.cloud",
input: "https://API.STACKIT.CLOUD/path",
isValid: true,
},
{
name: "STACKIT URL invalid",
allowedUrlDomain: "example.com",
Expand All @@ -137,6 +191,12 @@ func TestValidateURLDomain(t *testing.T) {
input: "https://www.test.example.com/",
isValid: true,
},
{
name: "custom domain boundary rejected",
allowedUrlDomain: "example.com",
input: "https://badexample.com",
isValid: false,
},
{
name: "every URL valid",
allowedUrlDomain: "",
Expand All @@ -153,6 +213,24 @@ func TestValidateURLDomain(t *testing.T) {
input: "http://example.stackit.cloud",
isValid: false,
},
{
name: "invalid protocol with allowed domain",
allowedUrlDomain: "stackit.cloud",
input: "http://api.stackit.cloud",
isValid: false,
},
{
name: "missing host",
allowedUrlDomain: "stackit.cloud",
input: "https:///path",
isValid: false,
},
{
name: "malformed URL",
allowedUrlDomain: "stackit.cloud",
input: "https://%zz",
isValid: false,
},
{
name: "no protocol",
input: "example.stackit.cloud",
Expand Down
Loading