package output import ( "os" "path/filepath" "strings" "testing" ) func TestSanitizeRedactsPasswordTokenAndKeyFields(t *testing.T) { t.Parallel() got := Sanitize("DB_PASSWORD=hunter2\naccess_token: abc123\napi-key = quoted-value\nplain=safe\n", nil) want := "DB_PASSWORD=[REDACTED]\naccess_token: [REDACTED]\napi-key = [REDACTED]\nplain=safe\n" if got != want { t.Errorf("Sanitize() = %q, want %q", got, want) } } func TestSanitizeRedactsSecretFileContents(t *testing.T) { t.Parallel() secretFile := filepath.Join(physicalTempDir(t), "provider-token") if err := os.WriteFile(secretFile, []byte("top-secret-value\n"), 0o600); err != nil { t.Fatal(err) } secrets, err := SecretValuesFromFiles([]string{secretFile}) if err != nil { t.Fatalf("SecretValuesFromFiles() error = %v", err) } got := Sanitize("request failed for top-secret-value", secrets) if got != "request failed for [REDACTED]" { t.Errorf("Sanitize() = %q, want redacted secret", got) } } func TestSecretValuesFromFilesRedactsNestedJSONScalars(t *testing.T) { t.Parallel() secretFile := filepath.Join(physicalTempDir(t), "pi-auth.json") contents := `{ "providers": { "dummy-provider": { "auth": { "key": "dummy-canary-json-key", "tokens": { "access": "dummy-canary-json-access", "refresh": "dummy-canary-json-refresh" } } } } }` if err := os.WriteFile(secretFile, []byte(contents), 0o600); err != nil { t.Fatal(err) } secrets, err := SecretValuesFromFiles([]string{secretFile}) if err != nil { t.Fatalf("SecretValuesFromFiles() error = %v", err) } got := Sanitize( "unlabelled dummy-canary-json-key dummy-canary-json-access dummy-canary-json-refresh", secrets, ) for _, canary := range []string{ "dummy-canary-json-key", "dummy-canary-json-access", "dummy-canary-json-refresh", } { if strings.Contains(got, canary) { t.Fatalf("Sanitize() exposed nested JSON scalar %q: %q", canary, got) } } } func TestSecretValuesFromFilesRedactsEveryDotenvBundleValue(t *testing.T) { t.Parallel() secretFile := filepath.Join(physicalTempDir(t), "thothii.secrets") contents := "MODEL_API_KEY=dummy-canary-bundle-model\n" + "DWH_PASSWORD='dummy-canary-bundle-dwh'\n" + "SESSION_TOKEN=\"dummy-canary-bundle-session\"\n" if err := os.WriteFile(secretFile, []byte(contents), 0o600); err != nil { t.Fatal(err) } secrets, err := SecretValuesFromFiles([]string{secretFile}) if err != nil { t.Fatalf("SecretValuesFromFiles() error = %v", err) } got := Sanitize( "unlabelled dummy-canary-bundle-model dummy-canary-bundle-dwh dummy-canary-bundle-session", secrets, ) for _, canary := range []string{ "dummy-canary-bundle-model", "dummy-canary-bundle-dwh", "dummy-canary-bundle-session", } { if strings.Contains(got, canary) { t.Fatalf("Sanitize() exposed dotenv bundle scalar %q: %q", canary, got) } } } func TestSecretValuesFromFilesAcceptsOpenSSHPrivateKey(t *testing.T) { t.Parallel() secretFile := filepath.Join(physicalTempDir(t), "git-ssh-key") contents := "-----BEGIN OPENSSH PRIVATE KEY-----\n" + "ZmFrZS1rZXktcGF5bG9hZA==\n" + "-----END OPENSSH PRIVATE KEY-----\n" if err := os.WriteFile(secretFile, []byte(contents), 0o600); err != nil { t.Fatal(err) } secrets, err := SecretValuesFromFiles([]string{secretFile}) if err != nil { t.Fatalf("SecretValuesFromFiles() error = %v, want OpenSSH key accepted", err) } if len(secrets) == 0 { t.Fatal("SecretValuesFromFiles() returned no values for OpenSSH key") } } func TestSanitizeRecognizesQuotedCredentialKeys(t *testing.T) { t.Parallel() got := Sanitize(`{"key":"dummy-canary-quoted-key","safe":"visible"}`, nil) if strings.Contains(got, "dummy-canary-quoted-key") || !strings.Contains(got, `"safe":"visible"`) { t.Fatalf("Sanitize() = %q, want only the quoted credential field redacted", got) } } func TestSecretValuesFromFilesRejectsMalformedJSONAndExcessiveScalars(t *testing.T) { t.Parallel() t.Run("malformed", func(t *testing.T) { secretFile := filepath.Join(physicalTempDir(t), "malformed-auth.json") if err := os.WriteFile(secretFile, []byte(`{"auth":{"key":"dummy-canary-malformed"}`), 0o600); err != nil { t.Fatal(err) } if _, err := SecretValuesFromFiles([]string{secretFile}); err == nil { t.Fatal("SecretValuesFromFiles() error = nil, want malformed-JSON failure") } }) t.Run("scalar bound", func(t *testing.T) { secretFile := filepath.Join(physicalTempDir(t), "many-auth-values.json") values := make([]string, 1025) for index := range values { values[index] = `"dummy-canary-value"` } if err := os.WriteFile(secretFile, []byte("["+strings.Join(values, ",")+"]"), 0o600); err != nil { t.Fatal(err) } if _, err := SecretValuesFromFiles([]string{secretFile}); err == nil { t.Fatal("SecretValuesFromFiles() error = nil, want scalar-count failure") } }) } func TestSecretValuesFromFilesRejectsOversizedFiles(t *testing.T) { t.Parallel() secretFile := filepath.Join(physicalTempDir(t), "oversized-token") if err := os.WriteFile(secretFile, make([]byte, 64*1024+1), 0o600); err != nil { t.Fatal(err) } if _, err := SecretValuesFromFiles([]string{secretFile}); err == nil { t.Fatal("SecretValuesFromFiles() error = nil, want oversized-file error") } } func physicalTempDir(t *testing.T) string { t.Helper() root, err := filepath.EvalSymlinks(os.TempDir()) if err != nil { t.Fatal(err) } directory, err := os.MkdirTemp(root, "tht-output-test-") if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = os.RemoveAll(directory) }) return directory }