@@ -305,6 +305,44 @@ describe("path-ignore for generated data files (#1946 follow-up)", () => {
305305 expect ( stderr ) . toContain ( "engine.input_too_large" ) ;
306306 expect ( stderr ) . not . toContain ( "skipped" ) ;
307307 } ) ;
308+
309+ test ( "(g) an ignore glob applies to a non-ASCII filename (core.quotePath=false)" , ( ) => {
310+ // Regression: git C-quotes non-ASCII paths by default (`"caf\303\251.csv"`),
311+ // which the glob can't match — the ignore rule would silently fail to apply
312+ // and the large export would still oversize-block. The hook forces
313+ // core.quotePath=false so the raw UTF-8 path matches.
314+ writeIgnoreFile ( "prospecting/exports/**/*.csv\n" ) ;
315+ const base = git ( [ "rev-parse" , "HEAD" ] ) ;
316+ fs . mkdirSync ( path . join ( repo , "prospecting" , "exports" ) , { recursive : true } ) ;
317+ fs . writeFileSync ( path . join ( repo , "prospecting" , "exports" , "café.csv" ) , BIG ) ;
318+ git ( [ "add" , "-A" ] ) ;
319+ git ( [ "commit" , "-q" , "-m" , "big export with non-ascii name" ] ) ;
320+ const head = git ( [ "rev-parse" , "HEAD" ] ) ;
321+ const { code, stderr } = runHook ( `refs/heads/main ${ head } refs/heads/main ${ base } \n` ) ;
322+ expect ( code ) . toBe ( 0 ) ;
323+ expect ( stderr ) . toContain ( "skipped 1 path(s)" ) ;
324+ expect ( stderr ) . toContain ( "café.csv" ) ;
325+ } ) ;
326+
327+ test ( "(h) a glob metacharacter in an ignored filename does NOT exclude a sibling (fail-open guard)" , ( ) => {
328+ // Fail-open regression (adversarial review): a real filename holding a `?`
329+ // is a legal path. A plain `:(exclude)export?.csv` pathspec is glob-ENABLED,
330+ // so git would ALSO drop `exportX.csv` (a sibling holding a real secret) from
331+ // the scan. `:(top,exclude,literal)` treats the name literally, so only the
332+ // exact ignored file is exempted and the sibling secret still blocks.
333+ // The glob is `export\?.csv` (escaped) so Bun.Glob matches ONLY the literal
334+ // `export?.csv` — isolating the git pathspec overreach, not Bun.Glob's own.
335+ writeIgnoreFile ( "export\\?.csv\n" ) ;
336+ const base = git ( [ "rev-parse" , "HEAD" ] ) ;
337+ fs . writeFileSync ( path . join ( repo , "export?.csv" ) , "benign generated data\n" ) ;
338+ fs . writeFileSync ( path . join ( repo , "exportX.csv" ) , "key AKIA1234567890ABCDEF\n" ) ;
339+ git ( [ "add" , "-A" ] ) ;
340+ git ( [ "commit" , "-q" , "-m" , "ignored ? file + sibling with a secret" ] ) ;
341+ const head = git ( [ "rev-parse" , "HEAD" ] ) ;
342+ const { code, stderr } = runHook ( `refs/heads/main ${ head } refs/heads/main ${ base } \n` ) ;
343+ expect ( code ) . toBe ( 1 ) ; // the sibling's credential must still block
344+ expect ( stderr ) . toContain ( "aws.access_key" ) ;
345+ } ) ;
308346} ) ;
309347
310348describe ( "install / chaining" , ( ) => {
0 commit comments