(t *testing.T)
| 6 | ) |
| 7 | |
| 8 | func TestValidateWebhookURL(t *testing.T) { |
| 9 | tests := []struct { |
| 10 | name string |
| 11 | url string |
| 12 | wantErr bool |
| 13 | }{ |
| 14 | // Valid URLs |
| 15 | {"valid https", "https://example.com/webhook", false}, |
| 16 | {"valid http", "http://example.com/callback", false}, |
| 17 | {"valid with port", "https://example.com:8080/hook", false}, |
| 18 | {"valid with path", "https://example.com/api/v1/webhook", false}, |
| 19 | |
| 20 | // Invalid schemes |
| 21 | {"ftp scheme", "ftp://example.com/hook", true}, |
| 22 | {"javascript scheme", "javascript:alert(1)", true}, |
| 23 | {"file scheme", "file:///etc/passwd", true}, |
| 24 | {"no scheme", "example.com/hook", true}, |
| 25 | |
| 26 | // Embedded credentials |
| 27 | {"with credentials", "https://user:pass@example.com/hook", true}, |
| 28 | |
| 29 | // Private IPs |
| 30 | {"loopback IPv4", "http://127.0.0.1/hook", true}, |
| 31 | {"loopback IPv6", "http://[::1]/hook", true}, |
| 32 | {"private 10.x", "http://10.0.0.1/hook", true}, |
| 33 | {"private 172.16.x", "http://172.16.0.1/hook", true}, |
| 34 | {"private 192.168.x", "http://192.168.1.1/hook", true}, |
| 35 | {"cloud metadata", "http://169.254.169.254/latest/meta-data/", true}, |
| 36 | {"link-local", "http://169.254.1.1/hook", true}, |
| 37 | {"unspecified", "http://0.0.0.0/hook", true}, |
| 38 | |
| 39 | // Widened reserved ranges |
| 40 | {"cgnat 100.64.x", "http://100.64.1.2/hook", true}, |
| 41 | {"ietf protocol 192.0.0.x", "http://192.0.0.8/hook", true}, |
| 42 | {"benchmarking 198.18.x", "http://198.19.0.1/hook", true}, |
| 43 | {"reserved class E 240.x", "http://240.0.0.1/hook", true}, |
| 44 | {"broadcast", "http://255.255.255.255/hook", true}, |
| 45 | |
| 46 | // Public addresses just outside the widened ranges must still pass |
| 47 | {"public above cgnat", "http://100.128.0.1/hook", false}, |
| 48 | {"public above 198.18/15", "http://198.20.0.1/hook", false}, |
| 49 | |
| 50 | // Hostnames resolving to private IPs |
| 51 | {"localhost", "http://localhost/hook", true}, |
| 52 | |
| 53 | // Empty/invalid |
| 54 | {"empty url", "", true}, |
| 55 | {"no host", "http:///path", true}, |
| 56 | } |
| 57 | |
| 58 | for _, tt := range tests { |
| 59 | t.Run(tt.name, func(t *testing.T) { |
| 60 | err := ValidateWebhookURL(tt.url) |
| 61 | if (err != nil) != tt.wantErr { |
| 62 | t.Errorf("ValidateWebhookURL(%q) error = %v, wantErr = %v", tt.url, err, tt.wantErr) |
| 63 | } |
| 64 | }) |
| 65 | } |
nothing calls this directly
no test coverage detected