mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-26 06:19:49 +00:00
d048631abc
A stored attachment name had three readers that disagreed. The extension
blocklist looked up filepath.Ext of the name as stored; the
Content-Disposition sanitiser dropped control characters, '"' and '\'
before serving it. So "x.s<VT>vg" or `x.s"vg` passed the blocklist
(".s<VT>vg" is no known extension) and was downloaded as "x.svg". For SVG,
whose bytes sniff as allowed text/xml, the extension is the whole defence.
The fix makes them read one string:
- DroppedFilenameRune (internal/attachments) is the ONE character rule:
Unicode control characters (C0, DEL, C1), '"' and '\'. The header
sanitiser uses it instead of its own switch.
- NormalizeFilename runs at BOTH ingest doors before ValidateUpload: the
upload handler, and bundle import, which stored the manifest's name
verbatim with none of the upload door's rules. It keeps the upload
door's leaf reduction and BUG-2803's fallback, drops the predicate's
characters, and trims trailing dots and spaces (which a download save
strips) unless that would leave nothing.
- ServedFilename covers legacy rows stored before this: a name whose
normalised extension is blocked is served as stem + ".bin".
Normalise rather than refuse: the attack still ends in the ordinary 415
extension_blocked, because its normalised name carries the extension it
was hiding, while a benign name with a stray tab is stored without it.
Visible change: stored attachment names lose control characters, quotes
and trailing dots/spaces.
Claude-Session: https://claude.ai/code/session_01Vf8uZmYdsrQqJtbAmjUFSX