package io // 本文件钉住 http 工具的**拦截日志**(M41 #16):rawURL 由模型/用户给,可能带 // `user:pass@` 或 `?api_key=`,而拦截日志是审计面、会被采集与转贴。旧实现把 rawURL // 原样记进 WARN,等于把凭据写进日志。 // // 现在只记来源主机与原因码;错误原文也不进日志 —— 解析失败时它包着 *url.Error, // 里面就是整条原串。 import ( "bytes" "context" "errors" "strings" "testing" "git.yeij.top/AskaEth/Cyrene_v2/internal/logger" ) // blockedLog 返回一个把日志写进 buffer 的 http 工具。 func blockedLog(t *testing.T) (*httpTool, *bytes.Buffer) { t.Helper() buf := &bytes.Buffer{} return httpToolForTest(t, WithLogger(logger.New(logger.Options{Out: buf, Level: "debug"}))), buf } // TestHTTPTool_BlockedLogHidesURLCredentials SSRF 拦截时日志只留来源与原因码。 func TestHTTPTool_BlockedLogHidesURLCredentials(t *testing.T) { t.Parallel() ht, logs := blockedLog(t) _, err := ht.Execute(context.Background(), map[string]any{"url": "https://user:pass@127.0.0.1/x"}) if !errors.Is(err, ErrSSRF) { t.Fatalf("err = %v, want ErrSSRF", err) } logged := logs.String() if !strings.Contains(logged, "io http: blocked request") { t.Fatalf("没有拦截日志,测试没覆盖到目标路径:\n%s", logged) } if strings.Contains(logged, "user:pass") || strings.Contains(logged, "pass@") { t.Fatalf("user:pass@ 进了拦截日志:\n%s", logged) } if !strings.Contains(logged, "reason=ssrf_blocked") { t.Fatalf("拦截日志缺原因码:\n%s", logged) } if !strings.Contains(logged, "[redacted]@127.0.0.1") { t.Fatalf("拦截日志缺来源主机(诊断面不能一起丢):\n%s", logged) } } // TestHTTPTool_BlockedLogHidesQueryCredentials 非 SSRF 的拒绝(这里是不支持的 scheme) // 同样不得带出 query 里的凭据。 func TestHTTPTool_BlockedLogHidesQueryCredentials(t *testing.T) { t.Parallel() ht, logs := blockedLog(t) _, err := ht.Execute(context.Background(), map[string]any{"url": "ftp://user:pass@files.example.com/x?api_key=QUERY-SECRET"}) if err == nil { t.Fatal("不支持的 scheme 却报成功") } logged := logs.String() if !strings.Contains(logged, "io http: blocked request") { t.Fatalf("没有拦截日志,测试没覆盖到目标路径:\n%s", logged) } if strings.Contains(logged, "QUERY-SECRET") || strings.Contains(logged, "user:pass") { t.Fatalf("拦截日志带出了原串里的凭据:\n%s", logged) } if !strings.Contains(logged, "reason=url_rejected") { t.Fatalf("拦截日志缺原因码:\n%s", logged) } }