Skip to content

fix(glob): strip trailing slash from gitignore-derived ignore patterns#1288

Merged
Simon (simonhj) merged 1 commit intov1.xfrom
simon/fix-glob-trailing-slash
May 1, 2026
Merged

fix(glob): strip trailing slash from gitignore-derived ignore patterns#1288
Simon (simonhj) merged 1 commit intov1.xfrom
simon/fix-glob-trailing-slash

Conversation

@simonhj
Copy link
Copy Markdown

@simonhj Simon (simonhj) commented Apr 28, 2026

Summary

TL;DR Buggy glob pattern generation caused traversal of ignored trees.

  • fast-glob silently discards ignore entries that end in / — the underlying micromatch matcher treats a trailing slash as a literal character that requires a matching trailing slash on the input path, and readdir entries never carry one. Validated this (to me non-obvious) behavior locally:
$ cat probe.mjs
import fg from 'fast-glob'

for (const pat of ['**/dist/', '**/dist', '**/dist/**']) {
  console.log(pat, await fg.glob(['**/*'], { cwd: 'fixture', ignore: [pat] }))
}

$ ls -T fixture/
fixture
├── a.txt
└── dist
    └── b.txt
$ node probe.mjs
**/dist/ [ 'a.txt', 'dist/b.txt' ]
**/dist [ 'a.txt' ]
**/dist/** [ 'a.txt' ]
  • The standard gitignore convention of writing directory entries as dist/ arrives at fast-glob as **/dist/ after ignorePatternToMinimatch, so fast-glob walks the directory anyway and the result has to be filtered out post-walk — wasting a readdir of the entire subtree on every call.
  • Strip the trailing slash before passing positives to fast-glob's ignore so the pattern actually matches.

Test plan

  • New regression test: directory ignored via trailing-slash pattern is correctly excluded.
  • All pre-existing globWithGitIgnore tests still pass (11 total: 10 existing + 1 new).
  • pnpm check:tsc clean.
  • `pnpm check:lint` clean on changed files.
  • End-to-end: socket fix against a fixture with a 300 000-file gitignored dist/ and --max-old-space-size=128 no longer OOMs and proceeds past the glob walk in well under a second.

Note

Medium Risk
Changes globbing ignore behavior for gitignore-derived directory entries, which can alter which files are scanned/returned. Low implementation complexity, but impacts filesystem traversal and results in tooling that relies on globWithGitIgnore.

Overview
Fixes globWithGitIgnore so gitignore directory patterns written with a trailing slash (e.g. dist/) actually prevent fast-glob from walking those directories by normalizing ignore patterns via a new stripTrailingSlash helper.

Adds a regression test confirming that dist/ in .gitignore excludes files under dist/ from glob results.

Reviewed by Cursor Bugbot for commit ee42879. Configure here.

fast-glob silently discards `ignore` entries that end in `/` — it treats
them as literal directory paths rather than glob patterns. The standard
gitignore convention of writing directory entries as `dist/` arrives
here as `**/dist/` after `ignorePatternToMinimatch`, which fast-glob
then drops, defeating the entire ignore. fast-glob walks the directory
anyway and the result has to be filtered out post-walk — wasting a
readdir of the entire subtree on every call.

Strip the trailing slash before passing to fast-glob so the pattern
actually matches.
@simonhj Simon (simonhj) marked this pull request as ready for review April 28, 2026 12:55
Copy link
Copy Markdown
Contributor

@mtorp Martin Torp (mtorp) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ✅ Thanks Simon (@simonhj)!

@jdalton
Copy link
Copy Markdown
Contributor

Thank you Simon (@simonhj). I'll update this in the @socketsecurity/lib for vNext versions.

Comment thread src/utils/glob.mts
@jdalton
Copy link
Copy Markdown
Contributor

Related to mrmlnc/fast-glob#437

John-David Dalton (jdalton) added a commit to SocketDev/socket-lib that referenced this pull request Apr 30, 2026
- Replace `new Array()` with `new ArrayCtor()` and `pattern.charCodeAt`
  with `StringPrototypeCharCodeAt` so the helper is hijack-resistant
  (prim audit was flagging both).
- Add 4 edge-case unit tests: mixed trailing/non-trailing patterns in
  same array, empty `ignore: []`, single-character `/` boundary
  (must not be stripped), no `ignore` option at all.
- Inline the upstream fast-glob URLs in the header comment
  (mrmlnc/fast-glob#437,
  SocketDev/socket-cli#1288) so a future
  reader can jump straight to the bug-hunt context without grepping.
@simonhj Simon (simonhj) merged commit 807b036 into v1.x May 1, 2026
16 of 21 checks passed
@simonhj Simon (simonhj) deleted the simon/fix-glob-trailing-slash branch May 1, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants