fix(vision): report only URL origin when an image source is rejected

fetchURL echoed the whole raw URL (path, query, userinfo) in the
ErrUnsupportedSource message, so a rejected source carrying a signed
query leaked it into logs and tickets. Route the URL exit through
trace.HostOf and fall back to a placeholder instead of the raw string.

Test pins origin-only output and goes red if the fix is reverted.
This commit is contained in:
AskaEth committed 2026-10-26 21:52:19 +08:00
1 parent d47185feb8
commit a5b3d40a74
2 files changed
+67 -1

No files matched your search

@@ -78,3 +78,56 @@ func TestDescribeDropsURLFromBuildRequestError(t *testing.T) {
t.Fatalf("err = %v, want ErrUpstream(分类不许被带偏)", err)
}
}
// TestFetchURLUnsupportedSourceReportsOriginOnly 钉住 M55 的那处 URL 出口:
// fetchURL 拒绝非 http(s) 来源时,错误串里只许有**来源**(scheme://host,
// 见 trace.HostOf),不得带路径、查询串与 userinfo —— 被拒的地址同样可能带
// 签名 query,而这条错误会进日志与工单。
//
// 变异:把 `sourceOrigin(rawURL)` 改回 `rawURL` ⇒ 本用例必红(secret、路径、
// 用户名都会出现);把兜底改回空串 ⇒ 第三条用例失去 "<unknown source>"。
func TestFetchURLUnsupportedSourceReportsOriginOnly(t *testing.T) {
t.Parallel()
cases := []struct {
name string
in string
wantOrigin string
leaks []string
}{
{
name: "带 query 的 ftp",
in: "ftp://files.example.com/a/b.png?access_token=" + urlCauseQuerySecret,
wantOrigin: "ftp://files.example.com",
leaks: []string{urlCauseQuerySecret, "access_token", "/a/b.png"},
},
{
name: "带 userinfo 的 ftp",
in: "ftp://" + urlCauseUser + ":svc-pass@files.example.com/p.png",
wantOrigin: "ftp://[redacted]@files.example.com",
leaks: []string{urlCauseUser, "svc-pass", "/p.png"},
},
{
name: "没有主机的 file",
in: "file:///etc/passwd?x=1",
wantOrigin: "<unknown source>",
leaks: []string{"/etc/passwd", "x=1"},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
_, _, err := fetchURL(context.Background(), c.in, nil)
if !errors.Is(err, ErrUnsupportedSource) {
t.Fatalf("err = %v, want ErrUnsupportedSource", err)
}
msg := err.Error()
for _, leak := range c.leaks {
if strings.Contains(msg, leak) {
t.Fatalf("错误串带出了地址细节 %q:%v", leak, err)
}
}
if !strings.Contains(msg, c.wantOrigin) {
t.Fatalf("错误串没给出可读来源 %q:%v", c.wantOrigin, err)
}
})
}
}