case 4715 - download file names checked

report/download and export/download (any download key), the log-file routes and
backup download built a path from the file name in the URL with Path.Combine
and no check, so on Windows a name with a folder part or an absolute path could
reach files outside the folder (security review F21). New helper
FileUtil.FullPathInFolderOrNull accepts only a bare file name that resolves
directly inside the folder; TemporaryFileExists and BackupFileExists use it
(the download routes already call them first), and so do both log routes.
A refused name gets the same 404 as a missing file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 12:20:25 -07:00
parent 705a54f9d8
commit e58ab2c100
4 changed files with 31 additions and 17 deletions

View File

@@ -181,7 +181,7 @@ John's "next release" cases for AyaNova (exported 2026-10-24). Each is its own s
| 4711 | JWT secret setting removed: the server generates its signing key once into `jwt-signing.key` in the data folder (4698 folded in) | F1. **Done** (placeholder-forged token 401; key survives restart; auth tests pass). Hosted setup script's secret step now does nothing; tidy later in `sockeye-client` |
| 4712 | Customer contact route allowlist + ownership checks | F13, F14, F15, F16, F17 |
| 4713 | Contact users limited to customer roles | F28 |
| 4715 | Download file names checked (one helper) | F21 |
| 4715 | Download file names checked (one helper) | F21. **Done** (`FileUtil.FullPathInFolderOrNull` in temp/backup exists checks and both log routes; test `DownloadNames`) |
| 4716 | Pick-list search text as SQL parameters | F18 |
| 4717 | KPI interval allowlist | F26 |
| 4718 | Report and translation import need create rights | F19, F24. **Done** (contact and Service 403, BizAdmin 202; test `ImportRights`) |