Security audit findings EXP2-SEC-01, SEC-IPC-04 and Codex #3 (symlink
redirection through externally extracted archives).
The ordinary install path hands every root `.eti` archive to an external
`unrar x` process and promotes the resulting staging directory to
`local/` as soon as the extractor exits 0. Nothing inspected what unrar
materialised. A symbolic link (or, on Windows, a junction) inside an
archive would survive promotion and later redirect the launch-time
settings rewrite in `apply_launch_settings_once`, the uninstall path,
or any script the game ships. The archives themselves are BLAKE3
verified against the bundled catalog before they can be installed, so a
hostile link would have to be published by the catalog operator; this
is defense in depth rather than a live remote exploit.
Two independent layers now guard promotion:
- Both `unrar` invocations (Tauri sidecar and peer-cli external
unpacker) pass `-ol-`, which makes unrar 7.x skip symbolic-link
entries entirely. The bundled 7.10 sidecar was checked against a
fixture archive.
- `install_inner`/`update_inner` walk the staging tree without
following links and refuse to promote it if any entry is a symlink or
(on Windows) carries the reparse-point attribute. The normal rollback
then removes staging and clears the install intent.
The audit's `-sl-` suggestion does not exist in unrar; `-sl<size>` is a
size filter. Post-extraction digest verification of every extracted
file remains out of scope for the ordinary path; Stream Install already
verifies each output entry.
Test plan: `just test` (new unix test installs with a fake unpacker
that plants a symlink and asserts install fails, `local/` is absent and
the intent is cleared; the peer-cli controlled-unrar test checks the
new argument position). Manual: install a fixture game via peer-cli.
Claude-Session: https://claude.ai/code/session_017C3Nbgwpdm3YNwZhhFLHwg