[low] Ebook symlinks: '~' in link targets, download TOCTOU #43

Open
opened 2026-10-18 17:46:55 +00:00 by jfro · 0 comments
Owner

Found by Nye reviewing PR #40 (#27, ebook symlinks). Non-blocking, low.

  1. SafePath realpath uses Path.expand(target, current), which expands a leading ~ in a symlink target to $HOME; POSIX treats it as a literal directory name. Only exploitable if $HOME is inside a library. Fix: for relative targets (Path.type(target) == :relative) use Path.join(current, target) |> Path.expand().
  2. Check-then-send TOCTOU in EbookController.download: the file could be swapped for a symlink between the check and send_download. Needs write access to the library.

FYI, accepted: after a library is deleted, its ebooks under a symlinked mount (like /media) won't download, because of the no-library "no symlinks at all" rule.

Found by Nye reviewing PR #40 (#27, ebook symlinks). Non-blocking, low. 1. `SafePath` realpath uses `Path.expand(target, current)`, which expands a leading `~` in a symlink target to `$HOME`; POSIX treats it as a literal directory name. Only exploitable if `$HOME` is inside a library. Fix: for relative targets (`Path.type(target) == :relative`) use `Path.join(current, target) |> Path.expand()`. 2. Check-then-send TOCTOU in `EbookController.download`: the file could be swapped for a symlink between the check and `send_download`. Needs write access to the library. FYI, accepted: after a library is deleted, its ebooks under a symlinked mount (like /media) won't download, because of the no-library "no symlinks at all" rule.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jfro/fuzzy_catalog#43
No description provided.