17da967f92
- Modified the session title generation template to focus on extracting only the intent of the user's question. - Enhanced the session service to include language context when generating titles. - Updated middleware to inject language into the request context. - Added a new test suite for validating SSRF safety of URLs.
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
package utils
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestIsSSRFSafeURL(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
rawURL string
|
|
wantOK bool
|
|
wantReasonSub string
|
|
}{
|
|
{
|
|
name: "empty URL",
|
|
rawURL: "",
|
|
wantOK: false,
|
|
wantReasonSub: "URL is empty",
|
|
},
|
|
{
|
|
name: "invalid scheme",
|
|
rawURL: "ftp://example.com/file.txt",
|
|
wantOK: false,
|
|
wantReasonSub: "invalid scheme",
|
|
},
|
|
{
|
|
name: "missing hostname",
|
|
rawURL: "https:///api/v1/ping",
|
|
wantOK: false,
|
|
wantReasonSub: "URL has no hostname",
|
|
},
|
|
{
|
|
name: "restricted hostname",
|
|
rawURL: "https://localhost/health",
|
|
wantOK: false,
|
|
wantReasonSub: "is restricted",
|
|
},
|
|
{
|
|
name: "restricted hostname suffix",
|
|
rawURL: "https://service.internal/status",
|
|
wantOK: false,
|
|
wantReasonSub: "hostname suffix .internal is restricted",
|
|
},
|
|
{
|
|
name: "direct IPv4 blocked",
|
|
rawURL: "https://8.8.8.8/dns-query",
|
|
wantOK: false,
|
|
wantReasonSub: "direct IP address access is not allowed",
|
|
},
|
|
{
|
|
name: "direct IPv6 blocked",
|
|
rawURL: "https://[2001:4860:4860::8888]/dns-query",
|
|
wantOK: false,
|
|
wantReasonSub: "direct IP address access is not allowed",
|
|
},
|
|
{
|
|
name: "IP-like decimal hostname blocked",
|
|
rawURL: "https://2130706433/",
|
|
wantOK: false,
|
|
wantReasonSub: "IP-like hostname format is not allowed",
|
|
},
|
|
{
|
|
name: "IP-like octal hostname blocked",
|
|
rawURL: "https://0177.0.0.1/",
|
|
wantOK: false,
|
|
wantReasonSub: "IP-like hostname format is not allowed",
|
|
},
|
|
{
|
|
name: "blocked internal service port",
|
|
rawURL: "https://example.com:3306/db",
|
|
wantOK: false,
|
|
wantReasonSub: "port 3306 is blocked for security reasons",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ok, reason := IsSSRFSafeURL(tt.rawURL)
|
|
if ok != tt.wantOK {
|
|
t.Fatalf("IsSSRFSafeURL(%q) ok = %v, want %v, reason = %q", tt.rawURL, ok, tt.wantOK, reason)
|
|
}
|
|
if tt.wantReasonSub != "" && !strings.Contains(reason, tt.wantReasonSub) {
|
|
t.Fatalf("IsSSRFSafeURL(%q) reason = %q, want contains %q", tt.rawURL, reason, tt.wantReasonSub)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsSSRFSafeURL_AllowPublicDomain(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ok, reason := IsSSRFSafeURL("https://example.com/path")
|
|
if !ok {
|
|
// This path depends on runtime DNS/network. If DNS is unavailable, skip to keep CI stable.
|
|
if strings.Contains(reason, "DNS resolution failed") {
|
|
t.Skipf("skip due to DNS unavailable in test environment: %s", reason)
|
|
}
|
|
t.Fatalf("expected public domain to be allowed, got ok=%v reason=%q", ok, reason)
|
|
}
|
|
}
|