@@ -674,16 +674,39 @@ export class FindingFilter {
674674 return false ; // No line number to check
675675 }
676676
677- // Extract the line from the diff
678- const lines = diffContent . split ( '\n' ) ;
679- const lineIndex = finding . line - 1 ;
677+ // Do not suppress concrete security findings just because the model's line
678+ // maps near hunk context. GitHub validation later decides whether it is postable.
679+ if ( this . isTrueSecurityIssue ( finding ) ) {
680+ return false ;
681+ }
680682
681- if ( lineIndex < 0 || lineIndex >= lines . length ) {
682- return false ; // Line number out of bounds
683+ const patchLike = diffContent . includes ( '@@' ) || diffContent . includes ( 'diff --git ' ) ;
684+ const mappedLine = this . findNewFileLineInDiff ( finding . file , finding . line , diffContent ) ;
685+
686+ if ( patchLike && mappedLine === null ) {
687+ return false ; // Cannot prove the line is wrong from this patch.
683688 }
684689
685- const line = lines [ lineIndex ] . trim ( ) ;
690+ if ( ! patchLike && mappedLine === null ) {
691+ // Legacy fallback for tests/plain snippets that pass raw code instead of a patch.
692+ const lines = diffContent . split ( '\n' ) ;
693+ const lineIndex = finding . line - 1 ;
694+
695+ if ( lineIndex < 0 || lineIndex >= lines . length ) {
696+ return false ; // Line number out of bounds
697+ }
698+
699+ return this . isBlankBraceOrCommentLine ( lines [ lineIndex ] . trim ( ) , finding . line ) ;
700+ }
686701
702+ if ( mappedLine === null ) {
703+ return false ;
704+ }
705+
706+ return this . isBlankBraceOrCommentLine ( mappedLine . trim ( ) , finding . line ) ;
707+ }
708+
709+ private isBlankBraceOrCommentLine ( line : string , lineNumber : number ) : boolean {
687710 // Check if the line is just a closing brace, blank, or comment
688711 if (
689712 line === '' ||
@@ -695,13 +718,61 @@ export class FindingFilter {
695718 line . startsWith ( '/*' ) ||
696719 line . startsWith ( '*' )
697720 ) {
698- logger . debug ( `Line ${ finding . line } is blank/brace/comment, likely incorrect line number` ) ;
721+ logger . debug ( `Line ${ lineNumber } is blank/brace/comment, likely incorrect line number` ) ;
699722 return true ;
700723 }
701724
702725 return false ;
703726 }
704727
728+ private findNewFileLineInDiff ( file : string , lineNumber : number , diffContent : string ) : string | null {
729+ let currentFile : string | null = null ;
730+ let newLine : number | null = null ;
731+
732+ for ( const rawLine of diffContent . split ( '\n' ) ) {
733+ const fileMatch = rawLine . match ( / ^ d i f f - - g i t a \/ .+ b \/ ( .+ ) $ / ) ;
734+ if ( fileMatch ) {
735+ currentFile = fileMatch [ 1 ] ;
736+ newLine = null ;
737+ continue ;
738+ }
739+
740+ const newFileMatch = rawLine . match ( / ^ \+ \+ \+ b \/ ( .+ ) $ / ) ;
741+ if ( newFileMatch ) {
742+ currentFile = newFileMatch [ 1 ] ;
743+ continue ;
744+ }
745+
746+ const hunkMatch = rawLine . match ( / ^ @ @ - \d + (?: , \d + ) ? \+ ( \d + ) (?: , \d + ) ? @ @ / ) ;
747+ if ( hunkMatch ) {
748+ newLine = Number ( hunkMatch [ 1 ] ) ;
749+ continue ;
750+ }
751+
752+ if ( newLine === null || currentFile !== file ) {
753+ continue ;
754+ }
755+
756+ if ( rawLine . startsWith ( '---' ) || rawLine . startsWith ( '+++' ) ) {
757+ continue ;
758+ }
759+
760+ if ( rawLine . startsWith ( '-' ) ) {
761+ continue ;
762+ }
763+
764+ if ( rawLine . startsWith ( '+' ) || rawLine . startsWith ( ' ' ) ) {
765+ const lineText = rawLine . slice ( 1 ) ;
766+ if ( newLine === lineNumber ) {
767+ return lineText ;
768+ }
769+ newLine ++ ;
770+ }
771+ }
772+
773+ return null ;
774+ }
775+
705776 /**
706777 * Check for invalid or suspicious line numbers that will cause GitHub API errors
707778 */
0 commit comments