@@ -582,9 +582,14 @@ function makeChecker(
582582 const newDiff = diffFromExpected ( contents ) ;
583583 if ( typeof newDiff === "string" ) return newDiff ;
584584 if ( newDiff . length === 0 ) return undefined ;
585+ // d.path segments come from contributor-controlled JSON object keys (e.g. dependency
586+ // names, tsconfig compilerOption keys), which may legally contain backticks, brackets,
587+ // parens, and embedded newlines. RFC-6901 only escapes `/` and `~`, so without further
588+ // sanitization a crafted key can break out of the inline-code span this string is
589+ // embedded in by createWelcomeComment and inject Markdown into a @typescript -bot comment.
585590 const diffDescription = newDiff . every ( ( d ) => / ^ \/ [ 0 - 9 ] + ( $ | \/ ) / . test ( d . path ) )
586591 ? ""
587- : ` (check: ${ newDiff . map ( ( d ) => `\`${ d . path . slice ( 1 ) . replace ( / \/ / g, "." ) } \`` ) . join ( ", " ) } )` ;
592+ : ` (check: ${ newDiff . map ( ( d ) => `\`${ mdSafePath ( d . path . slice ( 1 ) . replace ( / \/ / g, "." ) ) } \`` ) . join ( ", " ) } )` ;
588593 if ( ! oldText ) return `not ${ theExpectedForm } ${ diffDescription } ` ;
589594 const oldDiff = diffFromExpected ( oldText ) ;
590595 if ( typeof oldDiff === "string" ) return oldDiff ;
@@ -777,3 +782,10 @@ function isValidGithubUsername(name: unknown): name is string {
777782function isValidPackageDirectoryName ( name : string ) : boolean {
778783 return / ^ [ a - z 0 - 9 ] [ a - z 0 - 9 . _ - ] * $ / . test ( name ) ;
779784}
785+
786+ // Strip characters that would escape the inline-code span or inject Markdown structure when a
787+ // JSON-pointer-derived path (with attacker-controlled key segments) is interpolated into the
788+ // welcome comment via `file.suspect`.
789+ function mdSafePath ( s : string ) : string {
790+ return s . replace ( / [ ` \[ \] ( ) \r \n ] / g, "" ) ;
791+ }
0 commit comments