Make shell command resolution use Effect file metadata#3554
Draft
cursor[bot] wants to merge 1 commit into
Draft
Conversation
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Comment on lines
+53
to
+65
| function canExecuteFileInfo(info: FileSystem.File.Info): boolean { | ||
| if ((info.mode & POSIX_ANY_EXECUTE_MODE) === 0) return false; | ||
|
|
||
| const uid = getCurrentUid(); | ||
| if (uid === 0) return true; | ||
| if (uid !== undefined && Option.isSome(info.uid)) { | ||
| return info.uid.value === uid | ||
| ? (info.mode & POSIX_USER_EXECUTE_MODE) !== 0 | ||
| : canExecuteFileInfoForGroups(info); | ||
| } | ||
|
|
||
| return canExecuteFileInfoForGroups(info) || (info.mode & POSIX_ANY_EXECUTE_MODE) !== 0; | ||
| } |
Contributor
There was a problem hiding this comment.
🟠 High src/shell.ts:53
canExecuteFileInfo at line 64 treats a file as executable whenever any execute bit is set, even for unrelated users. A file with only the owner execute bit set (e.g., mode 0o100) incorrectly returns true for non-owners, causing isExecutableFile to report commands as available that the process cannot actually execute. This diverges from fs.accessSync(..., X_OK) behavior and leads to failed command resolution.
-function canExecuteFileInfo(info: FileSystem.File.Info): boolean {
- if ((info.mode & POSIX_ANY_EXECUTE_MODE) === 0) return false;
-
- const uid = getCurrentUid();
- if (uid === 0) return true;
- if (uid !== undefined && Option.isSome(info.uid)) {
- return info.uid.value === uid
- ? (info.mode & POSIX_USER_EXECUTE_MODE) !== 0
- : canExecuteFileInfoForGroups(info);
- }
-
- return canExecuteFileInfoForGroups(info) || (info.mode & POSIX_ANY_EXECUTE_MODE) !== 0;
-}🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/shared/src/shell.ts around lines 53-65:
`canExecuteFileInfo` at line 64 treats a file as executable whenever *any* execute bit is set, even for unrelated users. A file with only the owner execute bit set (e.g., mode `0o100`) incorrectly returns `true` for non-owners, causing `isExecutableFile` to report commands as available that the process cannot actually execute. This diverges from `fs.accessSync(..., X_OK)` behavior and leads to failed command resolution.
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.
What Changed
FileSystem.statmetadata andOptioninstead of anullsentinel plus synchronousnode:fsaccess checks.FileSystemlayer.Why
This keeps command resolution inside the Effect FileSystem capability, making the path more mockable/testable via layers while preserving POSIX executable-bit behavior.
Checklist
Note
Make shell command resolution check POSIX execute mode bits via Effect file metadata
canExecuteFilecall inisExecutableFilewith a stat-based check usingFileSystem.File.Infomode bits, so executability is determined by POSIX user/group/other execute bits relative to the current process uid and gids.canExecuteFileInfo,getCurrentUid, andgetCurrentGidsin shell.ts to encapsulate POSIX permission logic; root (uid 0) is always allowed.📊 Macroscope summarized 092b804. 1 file reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.