From 12ac25bd637eef5917986da2413efdaa9dd3165d Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Mon, 3 Aug 2026 17:25:44 +0000 Subject: [PATCH] Sanitize PromptKit profile fingerprint errors --- .../framework/llm/promptkit_client_test.go | 28 +++++++++++++++++++ .../llm/promptkit_profile_fingerprint.go | 4 +-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/internal/framework/llm/promptkit_client_test.go b/internal/framework/llm/promptkit_client_test.go index 4f82c3b..0273ce7 100644 --- a/internal/framework/llm/promptkit_client_test.go +++ b/internal/framework/llm/promptkit_client_test.go @@ -431,6 +431,34 @@ func TestPromptKitClientCheckpointFingerprintTracksProfileSource(t *testing.T) { } } +func TestPromptKitProfileFingerprintReadErrorsDoNotExposeSourcePaths(t *testing.T) { + for _, source := range []struct { + name string + profileDir string + profileFile string + }{ + { + name: "file", + profileFile: filepath.Join(t.TempDir(), "missing-profile.yaml"), + }, + { + name: "directory", + profileDir: filepath.Join(t.TempDir(), "missing-profiles"), + }, + } { + t.Run(source.name, func(t *testing.T) { + _, err := promptKitProfileFingerprint(source.profileDir, source.profileFile, "") + if err == nil { + t.Fatal("promptKitProfileFingerprint() error = nil, want source read failure") + } + if (source.profileDir != "" && strings.Contains(err.Error(), source.profileDir)) || + (source.profileFile != "" && strings.Contains(err.Error(), source.profileFile)) { + t.Fatalf("fingerprint error exposes profile source path: %q", err) + } + }) + } +} + func TestPromptKitClientUsesFallbackProfilesForExecutionAndInspection(t *testing.T) { assets := newTestPromptKitAssets(t) const profileID = "fallback-profile" diff --git a/internal/framework/llm/promptkit_profile_fingerprint.go b/internal/framework/llm/promptkit_profile_fingerprint.go index 052c286..1a33fc6 100644 --- a/internal/framework/llm/promptkit_profile_fingerprint.go +++ b/internal/framework/llm/promptkit_profile_fingerprint.go @@ -29,7 +29,7 @@ func promptKitProfileFingerprint(profileDir, profileFile, fallbackProfileDigest case strings.TrimSpace(profileFile) != "": data, err := os.ReadFile(strings.TrimSpace(profileFile)) if err != nil { - return CheckpointFingerprint{}, fmt.Errorf("read PromptKit profile file for checkpoint identity: %w", err) + return CheckpointFingerprint{}, fmt.Errorf("read PromptKit profile file for checkpoint identity") } writeFingerprintPart(hasher, data) case strings.TrimSpace(profileDir) != "": @@ -80,7 +80,7 @@ func promptKitProfileFileDigests(root string) ([][]byte, error) { return nil }) if err != nil { - return nil, fmt.Errorf("read PromptKit profile directory for checkpoint identity: %w", err) + return nil, fmt.Errorf("read PromptKit profile directory for checkpoint identity") } sort.Slice(digests, func(i, j int) bool { return string(digests[i]) < string(digests[j])