fix(fix): skip unreadable dirs in manifest discovery (EACCES scandir)#1347
Open
Martin Torp (mtorp) wants to merge 2 commits into
Open
fix(fix): skip unreadable dirs in manifest discovery (EACCES scandir)#1347Martin Torp (mtorp) wants to merge 2 commits into
Martin Torp (mtorp) wants to merge 2 commits into
Conversation
…unreadable dirs socket fix and socket scan create walk the project tree for .gitignore files to build their ignore set before collecting manifests. That walk ran through fast-glob with only the default ignore list — neither --exclude-paths nor socket.yml projectIgnorePaths were applied to it. A directory the running user cannot enter (a postgres pgdata dir owned by another uid, an unreadable Docker volume mount, etc.) therefore aborted the whole command with EACCES: permission denied, scandir '.../data/postgres/pgdata' during this discovery walk, before any exclusion could take effect — which is why excluding the path did not help. Thread projectIgnorePaths and --exclude-paths into the .gitignore discovery walk so explicit exclusions govern the entire discovery, and set suppressErrors on both that walk and the main package walk so an unreadable directory is skipped rather than crashing the run. A directory the user cannot read cannot contain manifests they could scan anyway. Add a regression test that reproduces the crash with a real chmod 000 directory (skipped under root and on Windows), and cut 1.1.112.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 21c7770. Configure here.
…rridden suppressErrors is the EACCES backstop for manifest discovery, not a tunable. Placing it before ...additionalOptions let a caller's options bag flip it back to false and re-introduce the crash. Move it after the spread so the safety invariant always holds. Flagged in review; no current caller passes suppressErrors, so behavior is unchanged.
Benjamin Barslev Nielsen (barslev)
approved these changes
May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
socket fix(andsocket scan create/socket scan reach) crash withwhen the project contains a directory the running user cannot enter — e.g. a postgres
pgdatadata directory owned by another uid (modedrwx------), or an unreadable Docker volume mount.#1339 added
--exclude-paths(andsocket.ymlprojectIgnorePathsalready existed) specifically to skip such directories, but neither worked — the command crashed identically even with the path excluded.Root cause
globWithGitIgnore(src/utils/glob.mts) runs two fast-glob walks:.gitignorediscovery walk (fastGlob.globStream(['**/.gitignore'], …)) to build the ignore set, then--exclude-paths(additionalIgnores) andprojectIgnorePathswere only ever applied to walk 2. Walk 1 runs first with just the default ignore list, so itscandirs straight into the unreadable directory and throws before any user exclusion can take effect. That's why excluding the path didn't help.Verified empirically with a reproduction (
chmod 000dir): the discovery walk throwsEACCES; the main walk with the exclude succeeds (the #1339 fix is correct, just unreachable); both walks withsuppressErrorssucceed.Fix
In
globWithGitIgnore:projectIgnorePaths+--exclude-pathsinto the.gitignorediscovery walk (negations dropped — for a discovery walk they could only re-include a subtree) so explicit exclusions govern the entire discovery, as the flag documents.suppressErrors: trueon both walks — a directory the user cannot read cannot contain manifests they could scan anyway, so skip it instead of aborting the whole run. This makes the tool robust without requiring any flag.Test
New regression test in
src/utils/glob.test.mtsreproduces the scenario with a realchmod 000directory (skipped under root, where perm checks are bypassed, and on Windows). It fails with the exactEACCES … scandirbefore the fix and passes after.Release
Cuts 1.1.112 (
package.json+CHANGELOG.md).Note
Medium Risk
Changes shared file-walking used by fix and scan; suppressErrors could mask rare filesystem errors, but scope is limited to skipping unreadable paths users could not scan anyway.
Overview
v1.1.112 fixes manifest discovery so
socket fixandsocket scan createno longer die onEACCES: permission denied, scandirwhen the repo contains directories the current user cannot read (e.g. Postgrespgdata, Docker volume mounts).globWithGitIgnoreruns a separate walk to find**/.gitignorebefore the main file walk.--exclude-pathsandsocket.ymlprojectIgnorePathswere only applied to the main walk, so the discovery walk could still enter an unreadable tree and abort before exclusions took effect. The PR applies the same ignore patterns to the discovery walk (dropping negated!patterns there) and setssuppressErrors: trueon both walks so unreadable directories are skipped instead of failing the whole command.A POSIX integration test uses a real
chmod 000directory (skipped on Windows and as root).Reviewed by Cursor Bugbot for commit 21c7770. Configure here.