fix(review): hash a JSON payload to prevent linked-issue-satisfaction cache-key collisions - #5976
Conversation
…Fingerprint The fingerprint "|"-joined free-form GitHub text fields (issueText, prTitle, prBody, diff), so an unescaped "|" inside one field could shift a boundary and make two genuinely different inputs serialize identically and collide on the same cache key. Build the payload with JSON.stringify, matching the sibling aiSlopCacheInputFingerprint, so distinct inputs always produce distinct fingerprints. Closes JSONbored#5939
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5976 +/- ##
==========================================
- Coverage 95.16% 95.16% -0.01%
==========================================
Files 589 589
Lines 46790 46789 -1
Branches 14943 14942 -1
==========================================
- Hits 44528 44527 -1
Misses 1511 1511
Partials 751 751
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-15 05:27:27 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 3 non-blocking
Linked issue satisfactionPartially addressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
Problem
linkedIssueSatisfactionCacheInputFingerprint(src/review/linked-issue-satisfaction-cache-input.ts) builds the payload it hashes into a linked-issue-satisfaction cache key by"|"-joining free-form GitHub text fields (issueText,prTitle,prBody,diff):None of that text is escaped, so a
|occurring naturally inside one field can shift the field boundary and produce the same joined string for two genuinely different inputs — e.g.{issueText: "foo|bar", prTitle: "baz"}and{issueText: "foo", prTitle: "bar|baz"}(other fields equal) serialize identically and hash to the same fingerprint/cache key, so one PR's linked-issue-satisfaction verdict can be replayed for a different PR.Its own comment says it "mirrors
ai-slop-cache-input.ts's fingerprint discipline" — but that sibling actually builds its payload viaJSON.stringify({...}), which structurally escapes delimiters and can't collide this way.Fix
Build the payload as a
JSON.stringify'd object, matching the siblingaiSlopCacheInputFingerprint. JSON escapes the field values ("foo|bar"vs"foo","bar|baz"serialize distinctly), so distinct inputs always produce distinct fingerprints. Field values are unchanged; only the serialization is structural now.Test
test/unit/linked-issue-satisfaction-cache.test.tsadds a case asserting the two previously-colliding inputs (issueText: "foo|bar" / prTitle: "baz"vsissueText: "foo" / prTitle: "bar|baz") now yield different fingerprints. The existing BYOK-toggle and cache round-trip tests are unchanged and still pass.Local: the fingerprint verification (distinct inputs differ; identical inputs stay deterministic) passes;
tsc --noEmitclean on the changed file.Closes #5939