mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-01 10:50:39 +02:00
fix(browse): restrictDirectoryPermissions warns and skips symlinked dirs
Closes the Windows Free Tests red: recent lane failures showed a
platform-unguarded POSIX mode-bit assertion ('Expected: 493' — a
symlink-skip test) from PR-branch variants; the KNOWN_WINDOWS_SAFE
force-include reason ('mode-bitmask hits are POSIX-branch only') did
not hold for that shape, and main had neither the guard nor the
behavior.
- product: lstat first; a symlinked dir gets a warning and a skip on
both platforms — chmod AND icacls dereference the link, so
restricting through a symlink hardens an unvetted target (and
/inheritance:r could lock out its real owner). All callers already
treat hardening as best-effort (try/catch).
- test: the symlink regression test, platform-aware — symlinkSync in
the house try/catch skip pattern (Windows runners without Developer
Mode can't create symlinks), mode-bit assertion guarded off win32,
behavior assertions (no throw, warning text, target readable)
everywhere; POSIX still proves the skip (0o755 unchanged, not 0o700)
- KNOWN_WINDOWS_SAFE reason updated to the now-true premise
20/20 pass on Linux.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
72a5246aae
commit
0d2f703f28
@@ -140,8 +140,29 @@ export function restrictFilePermissions(filePath: string): void {
|
||||
* (CI = container inherit) inherit the single-user-full ACL — important
|
||||
* because child creations in `fs.writeFileSync(...)` without explicit
|
||||
* `restrictFilePermissions` still end up owner-only.
|
||||
*
|
||||
* Symlinked dirs are warned about and SKIPPED, never followed: both
|
||||
* `chmod` and `icacls` dereference the link, so restricting through a
|
||||
* symlink hardens whatever the link points at — a target the caller never
|
||||
* vetted (and, with `/inheritance:r`, one we could lock its real owner out
|
||||
* of). Skipping is best-effort-consistent with the rest of this module:
|
||||
* the filesystem stays functional, we just don't hit the hardening target.
|
||||
*/
|
||||
export function restrictDirectoryPermissions(dirPath: string): void {
|
||||
try {
|
||||
if (fs.lstatSync(dirPath).isSymbolicLink()) {
|
||||
// biome-ignore lint/suspicious/noConsole: intentional user-facing warning
|
||||
console.warn(
|
||||
`[gstack] Refusing to restrict permissions through symlink ${dirPath} — skipping.\n` +
|
||||
` Restricting through a symlink would alter the link target instead. ` +
|
||||
`Harden the real directory directly.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// Path doesn't exist (or lstat failed) — fall through; both platform
|
||||
// branches below already swallow failures on missing paths.
|
||||
}
|
||||
if (process.platform === 'win32') {
|
||||
try {
|
||||
const user = currentUserPrincipal();
|
||||
|
||||
Reference in New Issue
Block a user