Skip to content

fix(ext/fs): truncate should not follow a terminal symlink#35239

Merged
bartlomieju merged 2 commits into
mainfrom
fix/truncate-nofollow-symlink
Jun 15, 2026
Merged

fix(ext/fs): truncate should not follow a terminal symlink#35239
bartlomieju merged 2 commits into
mainfrom
fix/truncate-nofollow-symlink

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

The permission check for Deno.truncate / Deno.truncateSync is performed
no-follow: it is checked against the path you name, without canonicalizing
symlinks. The implementation, however, opened the path with a plain
OpenOptions::write(true).open(path), which follows symlinks on Unix. A
writable symlink sitting at a path inside an allowed scope could therefore be
used to truncate (zero out) the file it points to, even when the target lives
outside that scope.

This opens the path with O_NOFOLLOW on Unix so that truncating through a
terminal symlink fails with ELOOP rather than silently truncating the link's
target. Truncating a regular file is unchanged, and only the final path
component is affected (intermediate symlinks are still resolved, matching the
existing path model). Windows behavior is unchanged.

Added unit tests covering both the sync and async paths: a symlink whose target
holds data is truncated through the link, and the operation now throws while
the target is left untouched.

The permission check for Deno.truncate / truncateSync is performed no-follow
(against the named path, without canonicalization), but the open followed
symlinks. A writable symlink inside an allowed scope could therefore be used to
zero out a file it points to outside that scope. Open the path with O_NOFOLLOW
on Unix so truncating through a terminal symlink fails instead of silently
truncating the target.
Assert the terminal-symlink case throws FilesystemLoop specifically (not a
permission error or silent success), and add coverage that an intermediate
directory symlink is still resolved so truncating a regular file reached
through it keeps working.
@bartlomieju
bartlomieju merged commit bb751c7 into main Jun 15, 2026
136 checks passed
@bartlomieju
bartlomieju deleted the fix/truncate-nofollow-symlink branch June 15, 2026 15:34
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.

1 participant