@@ -24,9 +24,20 @@ const mockGithubContext: any = {
2424 payload : { }
2525}
2626
27+ // Replicate @actions /core getInput behavior: it trims whitespace by default
28+ // (String.prototype.trim(), which strips characters such as a leading U+FEFF BOM)
29+ // unless trimWhitespace is explicitly set to false.
30+ const getInputImpl = ( name : string , options ?: { trimWhitespace ?: boolean } ) => {
31+ const val = inputs [ name ] ?? ''
32+ if ( options && options . trimWhitespace === false ) {
33+ return val
34+ }
35+ return typeof val === 'string' ? val . trim ( ) : val
36+ }
37+
2738// Mock @actions /core before loading input-helper
2839jest . unstable_mockModule ( '@actions/core' , ( ) => ( {
29- getInput : jest . fn ( ( name : string ) => inputs [ name ] ) ,
40+ getInput : jest . fn ( getInputImpl ) ,
3041 getBooleanInput : jest . fn ( ( name : string ) => inputs [ name ] ) ,
3142 getMultilineInput : jest . fn ( ( name : string ) =>
3243 inputs [ name ] ? String ( inputs [ name ] ) . split ( '\n' ) . filter ( Boolean ) : [ ]
@@ -76,9 +87,7 @@ describe('input-helper tests', () => {
7687 inputs = { }
7788 jest . clearAllMocks ( )
7889 // Re-apply default mocks
79- ; ( core . getInput as jest . Mock < any > ) . mockImplementation (
80- ( name : string ) => inputs [ name ]
81- )
90+ ; ( core . getInput as jest . Mock < any > ) . mockImplementation ( getInputImpl as any )
8291 mockDirectoryExistsSync . mockImplementation (
8392 ( p : string ) => p === gitHubWorkspace
8493 )
@@ -176,6 +185,36 @@ describe('input-helper tests', () => {
176185 expect ( settings . commit ) . toBeFalsy ( )
177186 } )
178187
188+ it ( 'does not reclassify a ref as sha when a BOM is prefixed' , async ( ) => {
189+ // A fork branch named "<U+FEFF>" + 40 hex chars. core.getInput trims the
190+ // BOM by default, which previously collapsed this into a bare SHA and
191+ // bypassed the unsafe fork PR checkout guard.
192+ inputs . ref = '\uFEFF522d932fae5296da51fdf431934425ecf891c6a2'
193+ const settings : IGitSourceSettings = await inputHelper . getInputs ( )
194+ expect ( settings . commit ) . toBeFalsy ( )
195+ expect ( settings . ref ) . toBe ( '522d932fae5296da51fdf431934425ecf891c6a2' )
196+ } )
197+
198+ it ( 'does not reclassify a sha-256 ref as sha when a BOM is prefixed' , async ( ) => {
199+ inputs . ref =
200+ '\uFEFF1111111111222222222233333333334444444444555555555566666666667777'
201+ const settings : IGitSourceSettings = await inputHelper . getInputs ( )
202+ expect ( settings . commit ) . toBeFalsy ( )
203+ expect ( settings . ref ) . toBe (
204+ '1111111111222222222233333333334444444444555555555566666666667777'
205+ )
206+ } )
207+
208+ it ( 'treats a sha surrounded by ascii whitespace as a commit' , async ( ) => {
209+ // ASCII whitespace can only come from the workflow author's YAML (git ref
210+ // names cannot contain it), so trimming it and treating the value as a
211+ // commit is safe.
212+ inputs . ref = ' 1111111111222222222233333333334444444444 '
213+ const settings : IGitSourceSettings = await inputHelper . getInputs ( )
214+ expect ( settings . ref ) . toBeFalsy ( )
215+ expect ( settings . commit ) . toBe ( '1111111111222222222233333333334444444444' )
216+ } )
217+
179218 it ( 'sets workflow organization ID' , async ( ) => {
180219 const settings : IGitSourceSettings = await inputHelper . getInputs ( )
181220 expect ( settings . workflowOrganizationId ) . toBe ( 123456 )
0 commit comments