fix(安全): 关闭白名单时保留最小校验与默认白名单
实现 allow_insecure_http 并在关闭校验时执行最小格式验证 - 关闭 allowlist 时要求 URL 可解析且 scheme 合规 - 响应头过滤关闭时使用默认白名单策略 - 更新相关文档、示例与测试覆盖
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -16,6 +17,38 @@ type ValidationOptions struct {
|
||||
AllowPrivate bool
|
||||
}
|
||||
|
||||
func ValidateURLFormat(raw string, allowInsecureHTTP bool) (string, error) {
|
||||
// 最小格式校验:仅保证 URL 可解析且 scheme 合规,不做白名单/私网/SSRF 校验
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
return "", errors.New("url is required")
|
||||
}
|
||||
|
||||
parsed, err := url.Parse(trimmed)
|
||||
if err != nil || parsed.Scheme == "" || parsed.Host == "" {
|
||||
return "", fmt.Errorf("invalid url: %s", trimmed)
|
||||
}
|
||||
|
||||
scheme := strings.ToLower(parsed.Scheme)
|
||||
if scheme != "https" && (!allowInsecureHTTP || scheme != "http") {
|
||||
return "", fmt.Errorf("invalid url scheme: %s", parsed.Scheme)
|
||||
}
|
||||
|
||||
host := strings.TrimSpace(parsed.Hostname())
|
||||
if host == "" {
|
||||
return "", errors.New("invalid host")
|
||||
}
|
||||
|
||||
if port := parsed.Port(); port != "" {
|
||||
num, err := strconv.Atoi(port)
|
||||
if err != nil || num <= 0 || num > 65535 {
|
||||
return "", fmt.Errorf("invalid port: %s", port)
|
||||
}
|
||||
}
|
||||
|
||||
return trimmed, nil
|
||||
}
|
||||
|
||||
func ValidateHTTPSURL(raw string, opts ValidationOptions) (string, error) {
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
|
||||
24
backend/internal/util/urlvalidator/validator_test.go
Normal file
24
backend/internal/util/urlvalidator/validator_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package urlvalidator
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestValidateURLFormat(t *testing.T) {
|
||||
if _, err := ValidateURLFormat("", false); err == nil {
|
||||
t.Fatalf("expected empty url to fail")
|
||||
}
|
||||
if _, err := ValidateURLFormat("://bad", false); err == nil {
|
||||
t.Fatalf("expected invalid url to fail")
|
||||
}
|
||||
if _, err := ValidateURLFormat("http://example.com", false); err == nil {
|
||||
t.Fatalf("expected http to fail when allow_insecure_http is false")
|
||||
}
|
||||
if _, err := ValidateURLFormat("https://example.com", false); err != nil {
|
||||
t.Fatalf("expected https to pass, got %v", err)
|
||||
}
|
||||
if _, err := ValidateURLFormat("http://example.com", true); err != nil {
|
||||
t.Fatalf("expected http to pass when allow_insecure_http is true, got %v", err)
|
||||
}
|
||||
if _, err := ValidateURLFormat("https://example.com:bad", true); err == nil {
|
||||
t.Fatalf("expected invalid port to fail")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user