Context
src/rules/advisory.ts's formatCheckRunOutput (around line 566) honors a finding's alreadyPublicSafe flag when building the check-run text field:
return [`${label} ${f.alreadyPublicSafe ? f.publicText : sanitizeForCheckRun(f.publicText)}`];
The comment right above it explains why (#7981): alreadyPublicSafe marks a fixed, engineer-authored message with no interpolated contributor/AI content, so scrubbing it through sanitizeForCheckRun would mangle a deliberately-worded string (e.g. turning "...secret, wallet, PAT..." into "...secret, [context], PAT...").
But the same findings are also rendered into inline check-run annotations by buildCheckRunAnnotations (same file, the loop starting around line 511 that calls addCandidate(path, ..., finding.title, finding.publicText)), and addCandidate unconditionally sanitizes:
const addCandidate = (path, line, level, title, message) => {
const safeTitle = sanitizeForCheckRun(title).slice(0, 255);
const safeMessage = sanitizeForCheckRun(message).slice(0, 65535);
...
addCandidate never receives or checks finding.alreadyPublicSafe. The result: the exact same finding renders verbatim in the check-run's text summary but gets scrubbed/mangled in the annotation for that same finding on the same PR — an inconsistency that reintroduces the bug class #7981 fixed, in a sibling code path #7981 didn't touch.
test/unit/rules.test.ts has coverage for alreadyPublicSafe against formatCheckRunOutput's text output but no coverage asserting the same behavior for buildCheckRunAnnotations.
Requirements
addCandidate inside buildCheckRunAnnotations (src/rules/advisory.ts) must skip sanitizeForCheckRun for the message argument when the originating finding has alreadyPublicSafe: true, mirroring the existing conditional in formatCheckRunOutput (f.alreadyPublicSafe ? f.publicText : sanitizeForCheckRun(f.publicText)).
- The
title argument should keep going through sanitizeForCheckRun unless there is a similar per-title safety flag already established elsewhere in the file — do not invent a new flag for the title; only change the message/publicText path to match the precedent in formatCheckRunOutput.
- Do not change behavior for findings where
alreadyPublicSafe is false/absent — they must continue to go through sanitizeForCheckRun exactly as today.
Deliverables
Test Coverage Requirements
This repo's Codecov patch gate requires 99%+ coverage of changed lines and branches. Cover both the alreadyPublicSafe: true branch (message passed through verbatim) and the alreadyPublicSafe: false/absent branch (message still sanitized) inside the modified addCandidate logic — both sides of the added conditional need an explicit assertion, not just one.
Expected Outcome
An alreadyPublicSafe finding's public text renders identically (verbatim, unscrubbed) whether it reaches GitHub through the check-run summary text or through an inline annotation — the two rendering paths for the same finding can no longer silently diverge.
Links & Resources
Context
src/rules/advisory.ts'sformatCheckRunOutput(around line 566) honors a finding'salreadyPublicSafeflag when building the check-runtextfield:The comment right above it explains why (#7981):
alreadyPublicSafemarks a fixed, engineer-authored message with no interpolated contributor/AI content, so scrubbing it throughsanitizeForCheckRunwould mangle a deliberately-worded string (e.g. turning"...secret, wallet, PAT..."into"...secret, [context], PAT...").But the same findings are also rendered into inline check-run annotations by
buildCheckRunAnnotations(same file, the loop starting around line 511 that callsaddCandidate(path, ..., finding.title, finding.publicText)), andaddCandidateunconditionally sanitizes:addCandidatenever receives or checksfinding.alreadyPublicSafe. The result: the exact same finding renders verbatim in the check-run'stextsummary but gets scrubbed/mangled in the annotation for that same finding on the same PR — an inconsistency that reintroduces the bug class #7981 fixed, in a sibling code path #7981 didn't touch.test/unit/rules.test.tshas coverage foralreadyPublicSafeagainstformatCheckRunOutput'stextoutput but no coverage asserting the same behavior forbuildCheckRunAnnotations.Requirements
addCandidateinsidebuildCheckRunAnnotations(src/rules/advisory.ts) must skipsanitizeForCheckRunfor themessageargument when the originating finding hasalreadyPublicSafe: true, mirroring the existing conditional informatCheckRunOutput(f.alreadyPublicSafe ? f.publicText : sanitizeForCheckRun(f.publicText)).titleargument should keep going throughsanitizeForCheckRununless there is a similar per-title safety flag already established elsewhere in the file — do not invent a new flag for the title; only change themessage/publicTextpath to match the precedent informatCheckRunOutput.alreadyPublicSafeisfalse/absent — they must continue to go throughsanitizeForCheckRunexactly as today.Deliverables
addCandidate's call site insidebuildCheckRunAnnotationsthreadsfinding.alreadyPublicSafethrough and conditionally skipssanitizeForCheckRunon the message, matchingformatCheckRunOutput's existing conditional.test/unit/rules.test.tsassertingbuildCheckRunAnnotationsrenders analreadyPublicSafe: truefinding'spublicTextverbatim (unscrubbed) in the annotationmessage, while a non-alreadyPublicSafefinding with the same forbidden-term-shaped text is still scrubbed.alreadyPublicSafefinding,formatCheckRunOutput'stextandbuildCheckRunAnnotations's annotationmessagecontain the identical unscrubbed string.Test Coverage Requirements
This repo's Codecov patch gate requires 99%+ coverage of changed lines and branches. Cover both the
alreadyPublicSafe: truebranch (message passed through verbatim) and thealreadyPublicSafe: false/absent branch (message still sanitized) inside the modifiedaddCandidatelogic — both sides of the added conditional need an explicit assertion, not just one.Expected Outcome
An
alreadyPublicSafefinding's public text renders identically (verbatim, unscrubbed) whether it reaches GitHub through the check-run summary text or through an inline annotation — the two rendering paths for the same finding can no longer silently diverge.Links & Resources
src/rules/advisory.ts—formatCheckRunOutput(existing correct behavior to mirror) andbuildCheckRunAnnotations/addCandidate(the gap)test/unit/rules.test.ts— existingalreadyPublicSafecoverage forformatCheckRunOutput, around line 876