Skip to content

Commit 380f4e6

Browse files
committed
Further refine URI validation and add more tests
1 parent 24e7c33 commit 380f4e6

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

internal/configs/configmaps_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,7 @@ func TestOpenTelemetryConfigurationInvalid(t *testing.T) {
16261626
{
16271627
configMap: &v1.ConfigMap{
16281628
Data: map[string]string{
1629-
"otel-exporter-endpoint": "something?invalid*30here",
1629+
"otel-exporter-endpoint": "something%invalid*30here",
16301630
},
16311631
},
16321632
expectedLoadModule: false,
@@ -1644,7 +1644,7 @@ func TestOpenTelemetryConfigurationInvalid(t *testing.T) {
16441644
},
16451645
},
16461646
expectedLoadModule: false,
1647-
expectedExporterEndpoint: "localhost:0",
1647+
expectedExporterEndpoint: "",
16481648
expectedExporterHeaderName: "",
16491649
expectedExporterHeaderValue: "",
16501650
expectedServiceName: "",

internal/validation/validation.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package validation
33
import (
44
"errors"
55
"fmt"
6+
"net/netip"
67
"net/url"
78
"regexp"
89
"strconv"
@@ -138,6 +139,17 @@ func ValidateURI(uri string, options ...URIValidationOption) error {
138139
return errors.New("user is not allowed")
139140
}
140141

142+
// Check whether we're dealing with an IPV6 address.
143+
checkIPv6 := parsed.Host
144+
if strings.Contains(checkIPv6, "[") {
145+
checkIPv6 = parsed.Hostname()
146+
}
147+
148+
if ip, err := netip.ParseAddr(checkIPv6); err == nil && !ip.Is4() {
149+
return fmt.Errorf("ipv6 addresses are not allowed")
150+
}
151+
152+
// Check whether the ports posted are valid.
141153
if parsed.Port() != "" {
142154
// Turn the string port into an integer and check if it's in the correct
143155
// range. The net.url.Parse does not check whether the port is the allowed
@@ -154,5 +166,15 @@ func ValidateURI(uri string, options ...URIValidationOption) error {
154166
}
155167
}
156168

169+
// Check whether each part of the domain is not too long.
170+
// This should really be octets
171+
for _, part := range strings.Split(parsed.Hostname(), ".") {
172+
// turn each part into a byte array to get a length of octets.
173+
// max length of a subdomain is 63 octets per RFC 1035.
174+
if len([]byte(part)) > 63 {
175+
return fmt.Errorf("invalid hostname part %s, value must be between 1 and 63 octets", part)
176+
}
177+
}
178+
157179
return nil
158180
}

internal/validation/validation_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,30 @@ func TestValidateURI(t *testing.T) {
172172
},
173173
wantErr: true,
174174
},
175+
{
176+
name: "uri that is an ipv6 address with a port",
177+
uri: "https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000",
178+
options: []URIValidationOption{},
179+
wantErr: true,
180+
},
181+
{
182+
name: "uri that is an ipv6 address without a port",
183+
uri: "https://2001:0db8:85a3:0000:0000:8a2e:0370:7334",
184+
options: []URIValidationOption{},
185+
wantErr: true,
186+
},
187+
{
188+
name: "uri that is a short ipv6 without port without scheme",
189+
uri: "fe80::1",
190+
options: []URIValidationOption{},
191+
wantErr: true,
192+
},
193+
{
194+
name: "uri that is a short ipv6 with a port without scheme",
195+
uri: "[fe80::1]:80",
196+
options: []URIValidationOption{},
197+
wantErr: true,
198+
},
175199
}
176200
for _, tt := range tests {
177201
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)