package contentpolicy import ( "io" "net/http" "strings" "testing" ) func testEngine(t *testing.T, action string) *Engine { t.Helper() policy := Policy{ID: "p1", Name: "secret", Action: action, Rules: []Rule{{Name: "token", Pattern: `sk-[A-Za-z0-9]{8,}`, Replacement: "[MASKED]"}}, Enabled: true} compiled, err := compilePolicy(policy) if err != nil { t.Fatal(err) } engine := &Engine{} engine.current.Store(&snapshot{policies: []compiledPolicy{compiled}}) return engine } func TestApplyRedactsOnlyTextualPromptFields(t *testing.T) { request, _ := http.NewRequest(http.MethodPost, "/v1/chat/completions", strings.NewReader(`{"model":"gpt-5","messages":[{"content":"use sk-12345678"}],"tools":[{"description":"keep sk-abcdefgh"}]}`)) result, err := testEngine(t, "redact").Apply(request, 1<<20, "key") if err != nil || !result.Redacted || result.Blocked { t.Fatalf("unexpected result %#v: %v", result, err) } body, _ := io.ReadAll(request.Body) text := string(body) if strings.Contains(text, "sk-12345678") || !strings.Contains(text, "keep sk-abcdefgh") { t.Fatalf("unexpected redaction: %s", text) } } func TestApplyBlocksWithoutReturningMatchedSecret(t *testing.T) { request, _ := http.NewRequest(http.MethodPost, "/v1/responses", strings.NewReader(`{"input":"sk-12345678"}`)) result, err := testEngine(t, "block").Apply(request, 1<<20, "") if err != nil || !result.Blocked || len(result.Matches) != 1 { t.Fatalf("unexpected result %#v: %v", result, err) } if strings.Contains(result.Matches[0].Rules[0], "12345678") { t.Fatal("match metadata leaked secret") } }