pdfcraft/apps/pdfcraft-cli/tests
jcl-bit f70c4caac9
Security: create save staging files with create_new (follow-up to #164) (#319)
* Security: create the --root staging file with create_new

Follow-up to #164. write_atomic staged every save at the fixed name
.<name>.pdfcraft-tmp and wrote it with fs::write, which follows a
symbolic link and writes through a hard link. So a link planted there,
in a folder someone else can write to, redirected the bytes to any file
the link pointed at.

The staging file now gets a random 64-bit suffix (std's RandomState,
keyed from the operating system's random source) and is opened with
OpenOptions::create_new, which fails if anything already has the name
(a file, a hard link, a symbolic link even when dangling), on Windows
(CREATE_NEW) as on Unix (O_EXCL). A taken name is skipped, never
opened; Windows reports a folder at the name as "access denied", which
counts as taken when something is there. After 16 taken names the save
fails and nothing is overwritten. A failed write or rename removes only
the file this save created. At most 128 bytes of the target's name go
into the staging name, so it fits every system's name limit.

The #164 tests that planted a sentinel at the old fixed name now also
compare folder listings, and say that the "is a folder" refusal is what
they check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Security: create the desktop app's save staging file with create_new

The same fix as the previous commit, for the desktop app.
editing::write_atomically, which Save, Save As, Export, Print to PDF,
signing and crash recovery all use, staged at
.<name>.pdfcraft-<pid>.tmp and opened it with File::create, which
follows a symbolic link and writes through a hard link. A process id is
easy to guess, so a link planted beside a document in a shared folder
could redirect a save into another file.

The staging file now gets a random 64-bit suffix and is opened with
OpenOptions::create_new; a taken name (on Windows, a folder reports
"access denied") is skipped, never opened, and after 16 the save fails
without overwriting anything. At most 128 bytes of the document's name
go into the staging name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-08 15:19:16 -04:00
..
edit.rs CLI: edit rejects unknown options instead of writing an unchanged copy (#133) (#227) 2026-10-08 03:39:27 -04:00
render.rs Issue #248: pdfcraft-cli render writes the format its --out name says (.png, .jpg, .tif or .pam) (#255) 2026-10-08 07:25:43 -04:00
run_root.rs Security: create save staging files with create_new (follow-up to #164) (#319) 2026-10-08 15:19:16 -04:00
split.rs Issue #249: pdfcraft-cli split creates --out-dir when it does not exist (#256) 2026-10-08 07:26:03 -04:00
stdout.rs Restore #196, #202, #203 and the macOS release-runner change, reverted by the i18n chain (#229) 2026-10-08 03:33:35 -04:00
text.rs CLI text tests: each protected-PDF test writes its own files (#267) 2026-10-08 08:33:26 -04:00