mustflow 2.116.1 → 2.116.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +1 -1
  2. package/templates/default/i18n.toml +72 -6
  3. package/templates/default/locales/en/.mustflow/skills/INDEX.md +37 -11
  4. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/SKILL.md +477 -0
  5. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/compiler-diagnostics-abi-linker-checklist.md +778 -0
  6. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/compiler-generators-properties-checklist.md +501 -0
  7. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/compiler-test-strategy-differential-checklist.md +498 -0
  8. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/debug-symbol-symbolication-checklist.md +412 -0
  9. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/ir-design-ssa-pass-pipeline-checklist.md +759 -0
  10. package/templates/default/locales/en/.mustflow/skills/compiler-engineering-review/references/miscompile-reduction-ir-checklist.md +434 -0
  11. package/templates/default/locales/en/.mustflow/skills/cross-platform-filesystem-safety/SKILL.md +55 -36
  12. package/templates/default/locales/en/.mustflow/skills/cross-platform-filesystem-safety/references/path-containment-handle-checklist.md +251 -0
  13. package/templates/default/locales/en/.mustflow/skills/file-upload-security-review/SKILL.md +133 -32
  14. package/templates/default/locales/en/.mustflow/skills/file-upload-security-review/references/file-upload-parser-ssrf-resource-checklist.md +306 -0
  15. package/templates/default/locales/en/.mustflow/skills/formal-verification-review/SKILL.md +310 -0
  16. package/templates/default/locales/en/.mustflow/skills/formal-verification-review/references/formal-concurrency-model-checking-smt-checklist.md +457 -0
  17. package/templates/default/locales/en/.mustflow/skills/formal-verification-review/references/formal-contracts-modeling-checklist.md +434 -0
  18. package/templates/default/locales/en/.mustflow/skills/formal-verification-review/references/formal-memory-bounds-ci-checklist.md +509 -0
  19. package/templates/default/locales/en/.mustflow/skills/fuzz-harness-review/SKILL.md +439 -0
  20. package/templates/default/locales/en/.mustflow/skills/fuzz-harness-review/references/fuzz-harness-campaign-checklist.md +379 -0
  21. package/templates/default/locales/en/.mustflow/skills/fuzz-harness-review/references/fuzz-oracle-triage-ci-checklist.md +307 -0
  22. package/templates/default/locales/en/.mustflow/skills/idempotency-integrity-review/SKILL.md +48 -28
  23. package/templates/default/locales/en/.mustflow/skills/idempotency-integrity-review/references/operation-ordering-stale-write-checklist.md +259 -0
  24. package/templates/default/locales/en/.mustflow/skills/input-boundary-validation-review/SKILL.md +329 -0
  25. package/templates/default/locales/en/.mustflow/skills/input-boundary-validation-review/references/input-boundary-security-checklist.md +319 -0
  26. package/templates/default/locales/en/.mustflow/skills/input-event-synchronization-review/SKILL.md +306 -0
  27. package/templates/default/locales/en/.mustflow/skills/input-event-synchronization-review/references/input-session-state-checklist.md +298 -0
  28. package/templates/default/locales/en/.mustflow/skills/input-event-synchronization-review/references/remote-input-transport-interaction-checklist.md +328 -0
  29. package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/SKILL.md +353 -0
  30. package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-diagnostics-recovery-checklist.md +267 -0
  31. package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-execution-closure-performance-checklist.md +428 -0
  32. package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-gc-verification-checklist.md +457 -0
  33. package/templates/default/locales/en/.mustflow/skills/interpreter-engineering-review/references/interpreter-semantics-runtime-checklist.md +391 -0
  34. package/templates/default/locales/en/.mustflow/skills/modal-loop-reentrancy-review/SKILL.md +294 -0
  35. package/templates/default/locales/en/.mustflow/skills/modal-loop-reentrancy-review/references/modal-loop-reentrancy-checklist.md +290 -0
  36. package/templates/default/locales/en/.mustflow/skills/modal-loop-reentrancy-review/references/nested-modal-state-lifetime-checklist.md +297 -0
  37. package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/SKILL.md +252 -0
  38. package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/references/dns-network-resolution-checklist.md +394 -0
  39. package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/references/language-symbol-resolution-checklist.md +282 -0
  40. package/templates/default/locales/en/.mustflow/skills/name-resolution-integrity-review/references/module-package-loader-resolution-checklist.md +352 -0
  41. package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/SKILL.md +103 -17
  42. package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/cst-ast-lowering-checklist.md +260 -0
  43. package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/lexer-tokenization-checklist.md +397 -0
  44. package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/tree-serialization-compatibility-checklist.md +164 -0
  45. package/templates/default/locales/en/.mustflow/skills/parser-engineering-review/references/tree-traversal-rewrite-checklist.md +209 -0
  46. package/templates/default/locales/en/.mustflow/skills/race-condition-review/SKILL.md +68 -11
  47. package/templates/default/locales/en/.mustflow/skills/race-condition-review/references/race-reproduction-memory-model-checklist.md +268 -0
  48. package/templates/default/locales/en/.mustflow/skills/routes.toml +151 -0
  49. package/templates/default/locales/en/.mustflow/skills/session-handoff-integrity-review/SKILL.md +343 -0
  50. package/templates/default/locales/en/.mustflow/skills/session-handoff-integrity-review/references/session-auth-stream-resume-checklist.md +413 -0
  51. package/templates/default/locales/en/.mustflow/skills/session-handoff-integrity-review/references/session-handoff-protocol-checklist.md +485 -0
  52. package/templates/default/locales/en/.mustflow/skills/two-phase-transition-integrity-review/SKILL.md +267 -0
  53. package/templates/default/locales/en/.mustflow/skills/two-phase-transition-integrity-review/references/admission-decision-recovery-checklist.md +308 -0
  54. package/templates/default/locales/en/.mustflow/skills/two-phase-transition-integrity-review/references/two-phase-transition-checklist.md +229 -0
  55. package/templates/default/locales/en/.mustflow/skills/ui-dispatch-lifecycle-review/SKILL.md +300 -0
  56. package/templates/default/locales/en/.mustflow/skills/ui-dispatch-lifecycle-review/references/ui-affinity-event-loop-checklist.md +277 -0
  57. package/templates/default/locales/en/.mustflow/skills/ui-dispatch-lifecycle-review/references/ui-dispatch-lifecycle-checklist.md +292 -0
  58. package/templates/default/manifest.toml +115 -1
@@ -2,7 +2,7 @@
2
2
  mustflow_doc: skill.file-upload-security-review
3
3
  locale: en
4
4
  canonical: true
5
- revision: 1
5
+ revision: 3
6
6
  lifecycle: mustflow-owned
7
7
  authority: procedure
8
8
  name: file-upload-security-review
@@ -30,7 +30,9 @@ metadata:
30
30
  <!-- mustflow-section: purpose -->
31
31
  ## Purpose
32
32
 
33
- Review file upload security as a full lifecycle, not as an extension or MIME-type checklist.
33
+ Review file upload security as a full lifecycle, not as an extension, MIME-type, or request-size
34
+ checklist. Accepting a file also selects parsers, expansion work, storage authority, and a future
35
+ serving path under attacker influence.
34
36
 
35
37
  The review question is not "does the upload route block `.exe`?" It is "what final bytes, filename,
36
38
  storage key, parser, visibility state, authorization check, and response headers can this uploaded
@@ -80,6 +82,9 @@ file reach after it enters the system?"
80
82
  - File identity ledger: original filename, normalized filename, final storage key, bucket or root,
81
83
  database record id, tenant or owner, checksum, size, content type, detected type, extension,
82
84
  visibility, status, and cleanup owner.
85
+ - Storage-access ledger: public opaque file id, tenant and object version used for authorization,
86
+ internal exact object key or root capability, original display name, storage adapter owning raw
87
+ path or key access, and every caller that can bypass that adapter.
83
88
  - Validation ledger: extension allowlist, decoding and normalization, content-type trust, signature
84
89
  checks, parser-based validation, image rewriting, metadata stripping, antivirus, CDR, size limits,
85
90
  count limits, quota, rate limits, and failure behavior.
@@ -91,6 +96,17 @@ file reach after it enters the system?"
91
96
  admin preview, email attachments, and public/private transition.
92
97
  - Existing tests, abuse cases, security docs, storage policy docs, configured command intents, and
93
98
  any unavailable cloud or scanner evidence.
99
+ - Byte-lineage ledger: quarantine object key and immutable version, received-byte digest, inspection
100
+ input digest, scanner and parser policy versions, approved object key and version, approved-byte
101
+ digest, and the operation that promoted or copied the approved bytes.
102
+ - Decoded-resource ledger: raster pixels and frames, document pages and layers, archive entries and
103
+ actual emitted bytes, parser CPU, memory, temporary disk, file descriptors, child processes,
104
+ elapsed time, output bytes, concurrency, retries, storage, and external-service cost.
105
+ - Remote-fetch ledger: original URL, canonical scheme and host, IDNA result, allowed port and method,
106
+ every resolved A and AAAA address, the address bound to the connection, TLS hostname, redirect
107
+ hops, egress decision, forwarded headers, and response limits.
108
+ - Read `references/file-upload-parser-ssrf-resource-checklist.md` when native or complex parsers,
109
+ archives, direct object-storage uploads, remote fetches, or resource-safety claims are in scope.
94
110
 
95
111
  <!-- mustflow-section: preconditions -->
96
112
  ## Preconditions
@@ -126,6 +142,8 @@ file reach after it enters the system?"
126
142
  store, record metadata, scan, transform, promote, preview, download, delete, and cleanup.
127
143
  - Include admin preview, email attachment, export, CDN, search index, and worker paths when they
128
144
  can read the uploaded bytes.
145
+ - Prove each accepted format and reachable parser is required by the product surface. Reject
146
+ unsupported containers or transformations instead of hardening an accidental feature.
129
147
  2. Treat frontend restrictions as usability only.
130
148
  - `<input accept>`, client-side size checks, mobile picker filters, and JavaScript extension
131
149
  checks do not prove security.
@@ -139,13 +157,24 @@ file reach after it enters the system?"
139
157
  - Blocklists for `.php`, `.jsp`, `.asp`, `.html`, `.svg`, config files, legacy plugin types, or
140
158
  executable server extensions are not enough by themselves.
141
159
  5. Validate the final storage name and key, not only the original filename.
142
- - Confirm the server generates the stored basename, object key, upload id, and path.
160
+ - Prefer external APIs that accept an opaque file id rather than a path, folder, prefix, or
161
+ storage key. Resolve authorization from the trusted `(tenant, object_id, version)` tuple before
162
+ loading the internal storage locator.
163
+ - Treat the original filename as display metadata. Confirm the server generates the stored
164
+ basename, exact object key, upload id, and local relative path.
165
+ - Keep raw local paths and object-store keys private to one storage adapter. Expose typed
166
+ operations such as get-by-authorized-id, stream-put, and extract-to-staging rather than
167
+ allowing controllers, workers, previews, and admin tools to reconstruct locators independently.
143
168
  - Treat `destination`, `folder`, `key`, `path`, `filename`, `bucket`, and callback-provided
144
169
  storage locations as attacker-controlled unless derived on the server.
145
170
  6. Prove path containment after normalization and symlink resolution.
146
- - `path.join(uploadDir, userName)` is not enough.
147
- - Check real path containment, absolute paths, drive letters, backslashes, `..`, symlinks,
148
- hardlinks, case-insensitive filesystems, and reserved names when local files are used.
171
+ - `path.join(uploadDir, userName)`, `realpath`, and a prefix check are early filters, not proof
172
+ when an attacker can change the tree.
173
+ - For local files, apply `cross-platform-filesystem-safety`: open relative to a trusted root
174
+ descriptor, HANDLE, or verified runtime root capability and keep the same opened-object
175
+ identity through scanning, transformation, promotion, and deletion.
176
+ - For object storage, directories are not a security boundary. Use the exact server-resolved key
177
+ and immutable version; do not authorize with user-built prefixes or prefix matching.
149
178
  7. Bound filenames and storage keys.
150
179
  - Check filename length, full path length, database column length, object-storage key length, log
151
180
  field length, CDN cache-key length, and error behavior for oversized or malformed names.
@@ -166,10 +195,11 @@ file reach after it enters the system?"
166
195
  - Polyglot files, metadata payloads, trailing content, and container formats can pass simple
167
196
  signature checks while still reaching dangerous parsers.
168
197
  12. Re-encode images when possible.
169
- - Decode and write a new image instead of storing user bytes directly when the product only
170
- needs raster images.
171
- - Strip EXIF, comments, thumbnails, ICC surprises, and other metadata unless product policy
172
- intentionally preserves them.
198
+ - Decode pixels and write a new image instead of storing user bytes directly when the product
199
+ only needs raster images.
200
+ - Apply orientation before size policy, choose a fixed output format and color space, and add
201
+ back only metadata the product explicitly needs. Do not copy arbitrary EXIF, comments,
202
+ thumbnails, profiles, or trailing bytes into the approved object.
173
203
  13. Treat SVG and HTML as active content.
174
204
  - Do not group SVG with ordinary raster images.
175
205
  - If SVG is allowed, require sanitization or rasterization, separate origin or strict CSP,
@@ -178,36 +208,66 @@ file reach after it enters the system?"
178
208
  - Check macros, embedded objects, JavaScript, external links, parser vulnerabilities, preview
179
209
  isolation, antivirus or CDR, and whether downloads are safer than inline rendering.
180
210
  15. Review archive extraction as the main feature.
181
- - For ZIP, tar, and nested archives, validate every entry path after normalization and prove it
182
- stays inside the extraction root.
183
- - Bound extracted file count, total uncompressed bytes, compression ratio, nesting depth,
184
- symlinks, hardlinks, absolute paths, duplicate entries, and processing time.
211
+ - For ZIP, tar, and nested archives, parse the complete bounded entry set before the first write
212
+ when feasible. Build one destination graph for duplicate normalized names, case and Unicode
213
+ aliases, alternate separators, file-directory prefix conflicts, and order-dependent link
214
+ traversal, then carry the validated entry object into extraction.
215
+ - Reject symlinks, hardlinks, devices, FIFOs, absolute paths, duplicate normalized names, and
216
+ unsupported entry types unless a narrower policy proves them safe.
217
+ - Ignore archive owner, group, mode, setuid, setgid, sticky, ACL, xattr, capability, and timestamp
218
+ metadata unless explicitly required and allowlisted. Create regular files and directories with
219
+ service-owned permissions inside a new attacker-nonwritable staging directory.
220
+ - Count actual bytes emitted while streaming extraction; do not trust archive headers or only a
221
+ compression ratio. Bound declared and actual size, sparse logical size and allocated storage,
222
+ entry and directory count, per-entry and cumulative emitted bytes, name length, depth, nesting,
223
+ parser work, and time under one shared budget.
224
+ - Pin and review the runtime extraction API and security options. Library filtering or path
225
+ cleanup remains defense in depth and does not replace the application entry policy.
226
+ - Treat every extracted entry as a fresh hostile upload with its own type, parser, filename,
227
+ and publication decision. Nested archives consume the parent budget rather than resetting it.
185
228
  16. Review CSV import and export for formula injection.
186
229
  - If user-supplied cells may later be opened in spreadsheets, handle cells beginning with `=`,
187
230
  `+`, `-`, `@`, tabs, carriage returns, line feeds, separators, quotes, and confusable
188
231
  variants according to local policy.
189
232
  17. Review remote URL import as SSRF plus upload.
190
- - Check scheme allowlists, redirect chains, DNS rebinding, localhost, private networks,
191
- link-local metadata endpoints, non-HTTP schemes, credential forwarding, response size,
192
- timeout, and final file validation.
233
+ - Prefer product-owned identifiers or provider integrations over arbitrary URLs. If URLs remain,
234
+ parse once and carry the same structured result into connection setup.
235
+ - Fix allowed schemes, ports, and methods; canonicalize IDNA hostnames; inspect every A and AAAA
236
+ result plus CNAME outcome; normalize IPv4, IPv6, mapped, loopback, private, link-local,
237
+ multicast, unspecified, and metadata ranges before connecting.
238
+ - Bind one validated address to the socket while preserving the canonical hostname for TLS and
239
+ HTTP host semantics. Revalidate every redirect as a new request and prevent DNS or proxy
240
+ layers from silently choosing a different address.
241
+ - Do not forward inbound authorization, cookies, proxy credentials, or arbitrary user headers.
242
+ Enforce egress policy, connect/read/total deadlines, response-byte and decoded-work limits,
243
+ then send the fetched response through the same quarantine and upload pipeline.
193
244
  18. Keep scanner and conversion work behind a publication gate.
194
245
  - A file that is pending scan, failed scan, pending conversion, or failed conversion should not
195
246
  be public, previewable, downloadable, indexed, or emailed unless policy explicitly allows it.
247
+ - Bind inspection results to an immutable quarantine object version and digest. A database row
248
+ saying `clean` is not proof if the referenced object can be overwritten afterward.
196
249
  19. Sandbox file parsers and scanners.
197
250
  - ImageMagick, ffmpeg, LibreOffice, PDF parsers, OCR tools, unzip, antivirus, and CDR engines
198
- need low privilege, no unnecessary network, timeouts, memory and CPU limits, temporary
199
- directory isolation, and controlled input paths.
251
+ need low privilege, no unnecessary network, explicit coder or delegate allowlists, CPU,
252
+ memory, temporary disk, file descriptor, child-process, wall-time, and output limits,
253
+ temporary-directory isolation, and controlled input paths.
254
+ - Treat timeout, crash, partial output, unavailable scanner, and limit exhaustion as rejection or
255
+ quarantine, never as an implicit pass.
200
256
  20. Validate direct-to-storage uploads in two phases.
201
257
  - Before issuing a signed upload URL, authorize the target resource and fix method, bucket, key,
202
258
  prefix, content type policy, checksum, size range, overwrite policy, and expiration.
203
- - After upload completion, verify actual object metadata before promoting it out of quarantine.
259
+ - After upload completion, read and hash the exact immutable object version that scanners and
260
+ parsers will inspect. Promote or copy only that exact version, record the approved digest and
261
+ policy or tool versions, and prevent the client from overwriting the approved destination.
204
262
  21. Treat presigned URLs as delegated authority.
205
263
  - Check method, bucket, key, prefix, expiry, reuse, checksum, content-length range, content type,
206
264
  ACL or public-read flags, revocation behavior, CDN caching, and whether the creator's
207
265
  privileges are too broad.
208
266
  22. Enforce tenant boundaries in storage keys and metadata.
209
- - Server-generated keys should include trusted tenant, organization, project, or resource
210
- context plus a random id when multi-tenant isolation matters.
267
+ - Authorize the `(tenant, object_id, version)` lookup before resolving the internal key. Knowing
268
+ or guessing a storage locator must not grant access.
269
+ - Server-generated keys should include trusted tenant, organization, project, or resource
270
+ context plus a random id when multi-tenant isolation matters.
211
271
  - Reads, writes, deletes, overwrites, cleanup, and promotion must use the same boundary.
212
272
  23. Recheck authorization at download and preview time.
213
273
  - Upload permission is not download permission.
@@ -216,16 +276,29 @@ file reach after it enters the system?"
216
276
  24. Set response headers deliberately.
217
277
  - Use safe `Content-Type`; default ambiguous private downloads to `application/octet-stream`.
218
278
  - Use `Content-Disposition: attachment` when inline rendering is not required.
219
- - Add `X-Content-Type-Options: nosniff` and review CSP, origin isolation, and CDN header
220
- preservation where browser execution risk exists.
279
+ - Add `X-Content-Type-Options: nosniff` and review CSP, origin isolation, and CDN header
280
+ preservation where browser execution risk exists.
281
+ - Treat `Content-Disposition` filenames as presentation only. Remove CR/LF and path segments,
282
+ generate a conservative ASCII `filename` fallback plus a correctly encoded UTF-8 `filename*`,
283
+ and never feed either value back into storage lookup or authorization.
284
+ - Serve static assets through an immutable build manifest. Keep SPA fallback fixed to one known
285
+ `index.html` after route classification instead of trying alternate extensions or arbitrary
286
+ filesystem candidates derived from the URL.
221
287
  25. Treat filename display as an injection surface.
222
288
  - Escape original filenames in HTML, email, admin tables, JSON-in-script, logs, and support
223
289
  views.
224
- - For `Content-Disposition`, remove CR/LF and encode filenames safely for header context.
290
+ - For `Content-Disposition`, remove CR/LF and encode filenames safely for header context.
291
+ - Escape control characters and line breaks before logging rejected names. Record a bounded
292
+ display value and stable policy code, not the raw attacker-controlled string.
225
293
  26. Apply resource limits at every layer.
226
294
  - Bound request body size, per-file size, file count, concurrent uploads, chunk count, multipart
227
295
  sessions, user quota, tenant quota, daily quota, extracted size, transformed size, preview
228
296
  time, and retry volume.
297
+ - Bound decoded pixels, cumulative animation frames, pages, layers, archive entries and actual
298
+ emitted bytes, parser CPU and memory, temporary disk, file descriptors, child processes,
299
+ output bytes, queue depth, concurrent conversions, storage growth, and paid external work.
300
+ - Put deadlines and cancellation around the whole operation; a per-read timeout does not cap a
301
+ peer that continuously dribbles bytes.
229
302
  27. Revalidate chunked and multipart uploads at assembly time.
230
303
  - Check final file size, content type, signature, chunk order, chunk count, checksum, session
231
304
  expiration, stale partial cleanup, and final key ownership after assembly.
@@ -241,7 +314,23 @@ file reach after it enters the system?"
241
314
  - Cover disallowed type, spoofed MIME, renamed extension, encoded extension, double extension,
242
315
  oversize body, quota exceeded, path traversal, archive escape, zip bomb, SVG active content,
243
316
  CSV formula, unauthorized upload target, unauthorized download, pending-scan download,
244
- presigned overwrite, stale multipart session, and remote URL SSRF where relevant.
317
+ presigned overwrite, stale multipart session, type-detector disagreement, cumulative image
318
+ pixels or frames, archive special entries and actual emitted-byte overflow, parser timeout or
319
+ crash, quarantine-object replacement, DNS or redirect rebinding, forbidden egress, credential
320
+ forwarding, fetched-response revalidation, path-shaped public API input, prefix-authorized
321
+ object keys, file-directory archive conflicts, archive metadata restoration, sparse logical
322
+ size overflow, `Content-Disposition` CR/LF, static-extension fallback, and raw-name log
323
+ injection where relevant.
324
+ - Assert rejected, crashed, timed-out, or partially processed files never become public,
325
+ previewable, downloadable, indexed, emailed, or reusable as approved inputs.
326
+ - Classify each finding as publication-blocking, high-risk but contained, or defense-in-depth,
327
+ and name the exact missing invariant or evidence that would change the decision.
328
+ - Use publication-blocking when exact-byte identity, authorization, parser or expansion
329
+ bounds, remote-destination control, or fail-closed publication gating is missing.
330
+ - Use high-risk but contained only when an independent enforced control proves the risky
331
+ bytes or operation cannot reach a published, privileged, or cross-tenant path. Partial
332
+ hardening of the same vulnerable control is not containment.
333
+ - Use defense-in-depth only after the required lifecycle invariants are already proven.
245
334
 
246
335
  <!-- mustflow-section: postconditions -->
247
336
  ## Postconditions
@@ -250,8 +339,14 @@ file reach after it enters the system?"
250
339
  record, validation gates, processing tools, visibility state, serving path, and cleanup owner.
251
340
  - Client-provided filenames, MIME labels, paths, keys, URLs, sizes, checksums, tenants, owners, and
252
341
  visibility flags are either ignored, verified, or explicitly reported as risky.
342
+ - Public file identifiers, authorization tuples, display names, internal exact keys, immutable
343
+ versions, and local root capabilities are distinct; raw locators remain behind one storage adapter.
253
344
  - File type validation is tied to normalized final names and actual bytes, not only extension or
254
345
  request headers.
346
+ - Scanner and parser results are bound to the exact immutable object version and digest later
347
+ promoted or served, with tool or policy versions recorded where decisions depend on them.
348
+ - Decoded, expanded, parser, concurrency, output, storage, and external-cost budgets are explicit;
349
+ archive and remote-fetch paths cannot reset or bypass them.
255
350
  - Upload, processing, promotion, preview, download, CDN, email, admin, and cleanup paths are checked
256
351
  or explicitly scoped out.
257
352
  - Denial-case tests or missing evidence are named from the attacker-controlled file lifecycle.
@@ -273,9 +368,10 @@ Use configured oneshot command intents when available:
273
368
  - `mustflow_check`
274
369
 
275
370
  Prefer the narrowest configured tests that prove file lifecycle denial behavior: disallowed type,
276
- spoofed MIME, normalized extension bypass, path traversal, archive escape, resource limit,
277
- unauthorized upload target, unauthorized download, pending-scan access, presigned policy, and remote
278
- URL rejection.
371
+ spoofed MIME, normalized extension bypass, path traversal, archive escape or actual-byte overflow,
372
+ decoded-media and parser limits, immutable-object binding, unauthorized upload target, unauthorized
373
+ download, pending-scan access, presigned policy, DNS and redirect rebinding, and fetched-response
374
+ revalidation.
279
375
 
280
376
  <!-- mustflow-section: failure-handling -->
281
377
  ## Failure Handling
@@ -295,10 +391,15 @@ URL rejection.
295
391
  ## Output Format
296
392
 
297
393
  - File upload security reviewed
298
- - Upload entrypoints, file identity, storage, validation, processing, serving, and cleanup map
299
- - Filename, type, path, overwrite, web-root, parser, archive, CSV, remote URL, scanner, signed URL,
300
- tenant, authorization, header, and resource-limit findings
394
+ - Upload entrypoints, byte lineage, immutable object versions and digests, storage, validation,
395
+ processing, serving, and cleanup map
396
+ - Filename, opaque identity, exact storage key, root capability, type, path, overwrite, web-root,
397
+ static-manifest serving, parser isolation, decoded-resource, archive metadata and sparse budgets, CSV,
398
+ remote-fetch resolution and redirect, scanner, signed URL, tenant, authorization, header, and
399
+ resource-limit findings
301
400
  - Fixes made or recommendation
401
+ - Finding disposition: publication-blocking, high-risk but contained, or defense-in-depth, with the
402
+ enforcing control and missing invariant or evidence needed to change the decision
302
403
  - Denial tests, fixtures, or invariant evidence
303
404
  - Command intents run
304
405
  - Skipped checks and reasons
@@ -0,0 +1,306 @@
1
+ # File Upload Parser, SSRF, and Resource Checklist
2
+
3
+ Use this reference when the short procedure needs concrete review ledgers for complex parsers,
4
+ archive extraction, direct object-storage uploads, remote imports, or resource-exhaustion claims.
5
+ It is a review aid, not a universal numeric policy. Record repository-specific limits and evidence.
6
+
7
+ ## Contents
8
+
9
+ 1. [Lifecycle and publication states](#1-lifecycle-and-publication-states)
10
+ 2. [Byte lineage and immutable objects](#2-byte-lineage-and-immutable-objects)
11
+ 3. [Type and parser decision matrix](#3-type-and-parser-decision-matrix)
12
+ 4. [Decoded media and document budgets](#4-decoded-media-and-document-budgets)
13
+ 5. [Archive extraction ledger](#5-archive-extraction-ledger)
14
+ 6. [Remote-fetch SSRF ledger](#6-remote-fetch-ssrf-ledger)
15
+ 7. [Parser sandbox and capability matrix](#7-parser-sandbox-and-capability-matrix)
16
+ 8. [Resource, concurrency, and cost budget](#8-resource-concurrency-and-cost-budget)
17
+ 9. [Layer responsibility handoff](#9-layer-responsibility-handoff)
18
+ 10. [Denial and differential test matrix](#10-denial-and-differential-test-matrix)
19
+ 11. [Primary reference anchors](#11-primary-reference-anchors)
20
+
21
+ ## 1. Lifecycle and publication states
22
+
23
+ Model visibility as an explicit state machine. A useful minimum is:
24
+
25
+ `receiving -> quarantined -> inspecting -> approved -> published`
26
+
27
+ Terminal or side states include `rejected`, `processing_failed`, `expired`, and `deleted`.
28
+
29
+ For every state, record:
30
+
31
+ | Question | Evidence |
32
+ | --- | --- |
33
+ | Who may write or replace bytes? | Storage policy and application authorization |
34
+ | Who may read bytes? | Download, preview, worker, admin, and support paths |
35
+ | Which parser may run? | Tool and policy version |
36
+ | Can a CDN, indexer, emailer, or previewer observe it? | Publication gate |
37
+ | What advances the state? | Atomic condition and authenticated actor |
38
+ | What happens on timeout, crash, or unavailable scanner? | Fail-closed transition |
39
+
40
+ Do not treat a `clean = true` column as the state machine. The decision must identify the exact
41
+ bytes inspected and the exact bytes made visible.
42
+
43
+ ## 2. Byte lineage and immutable objects
44
+
45
+ Maintain this ledger across receive, inspect, transform, promote, and serve:
46
+
47
+ | Field | Required meaning |
48
+ | --- | --- |
49
+ | `upload_id` | Server-issued lifecycle identifier |
50
+ | `quarantine_key` | Server-generated private location |
51
+ | `quarantine_version` | Immutable object version or equivalent generation id |
52
+ | `received_digest` | Digest computed from bytes actually received |
53
+ | `inspected_digest` | Digest of exact scanner/parser input |
54
+ | `inspection_policy_version` | Allowlist, parser, scanner, and budget policy identity |
55
+ | `derived_digest` | Digest of rewritten or converted output when applicable |
56
+ | `approved_key` and `approved_version` | Exact immutable object selected for serving |
57
+ | `approved_digest` | Digest verified during promotion or copy |
58
+ | `publication_event` | Atomic operation that made the object visible |
59
+
60
+ Reject these broken chains:
61
+
62
+ - the client can overwrite a quarantined object after inspection;
63
+ - the scanner reads `key` without an immutable version while the uploader can replace `key`;
64
+ - metadata is approved but a later download resolves a different object generation;
65
+ - transformation output is public before its own type and resource checks finish;
66
+ - promotion copies the latest object instead of the inspected object;
67
+ - retries overwrite a prior approved destination without an explicit replacement policy.
68
+
69
+ Keep these identities separate:
70
+
71
+ | Identity | Security role |
72
+ | --- | --- |
73
+ | Public `file_id` | Opaque request identifier with no path meaning. |
74
+ | `(tenant, object_id, version)` | Authorization lookup tuple resolved before any storage locator is used. |
75
+ | Original filename | Display metadata only; never a storage key or authorization fact. |
76
+ | Exact object key and immutable version | Server-owned object-store locator returned by the authorized record. Prefix agreement is not authorization. |
77
+ | Local root capability and validated relative entry | Filesystem adapter authority; never exposed as a controller or queue string. |
78
+
79
+ Require one storage adapter to own raw path and object-key APIs. Controllers, workers, thumbnailers,
80
+ archive tools, admin surfaces, and serving code should consume typed file identities or opened streams
81
+ rather than reconstructing paths or prefixes independently.
82
+
83
+ ## 3. Type and parser decision matrix
84
+
85
+ Do not ask whether one detector is authoritative. Ask which parser the product needs and which
86
+ evidence is sufficient to select it.
87
+
88
+ | Signal | Use | Never proves alone |
89
+ | --- | --- | --- |
90
+ | Normalized extension | Product allowlist and UX | Actual byte format |
91
+ | Request `Content-Type` | Logging and disagreement detection | Safe parser choice |
92
+ | Signature or magic | Candidate family | Entire container safety |
93
+ | Structural parser | Format conformance | Safe active content or bounded cost |
94
+ | Rewrite/conversion | Produces controlled derivative | Safety if parser is unbounded |
95
+
96
+ Record disagreement policy. An allowed extension with a mismatched signature or parser result
97
+ should not silently choose whichever interpretation is most permissive.
98
+
99
+ For raster-only products, prefer decode-to-pixels and deterministic rewrite. Apply orientation,
100
+ then enforce dimensions, select a fixed output format and color space, and add back only required
101
+ metadata. Do not preserve arbitrary original chunks or trailing bytes.
102
+
103
+ Treat SVG, HTML, PDF, Office, media containers, fonts, and archives as parser-bearing formats with
104
+ their own active-content and resource policies.
105
+
106
+ ## 4. Decoded media and document budgets
107
+
108
+ Compressed bytes are only the wire envelope. Record limits on decoded work:
109
+
110
+ | Format family | Minimum budget dimensions |
111
+ | --- | --- |
112
+ | Raster image | Width, height, total pixels, channels, bit depth, output bytes |
113
+ | Animated image | Per-frame pixels, cumulative frame pixels, frame count, duration |
114
+ | Layered image | Layers, cumulative layer pixels, memory, temporary disk |
115
+ | PDF | Pages, objects, recursion, embedded files, render pixels, output bytes |
116
+ | Office document | Entries, XML nodes, relationships, embedded objects, pages or slides |
117
+ | Audio/video | Duration, tracks, dimensions, frames, decoded bytes, transcode time |
118
+ | OCR | Input pixels or pages, languages, CPU, elapsed time, output text bytes |
119
+
120
+ Limits must apply before or during allocation. A check performed only after a decoder has allocated
121
+ the full image or document does not protect the process.
122
+
123
+ For multi-item containers, track both per-item and cumulative budgets. An animation with many small
124
+ frames or a PDF with many modest pages can exhaust resources while each item passes alone.
125
+
126
+ ## 5. Archive extraction ledger
127
+
128
+ Before extraction, define allowed archive families and allowed entry types. During extraction,
129
+ record and enforce:
130
+
131
+ | Budget or invariant | Enforcement point |
132
+ | --- | --- |
133
+ | Complete bounded entry inventory | Before the first filesystem write when the format permits it |
134
+ | File-directory prefix graph | Before accepting both `a` and `a/b` or another order-dependent topology |
135
+ | Normalized contained path | Before creating each entry |
136
+ | Duplicate normalized name | Before overwrite or allocation |
137
+ | Entry type | Before filesystem operation |
138
+ | Metadata allowlist | Before applying owner, group, mode, timestamp, ACL, xattr, or capability fields |
139
+ | Per-entry emitted bytes | While streaming output |
140
+ | Logical size and sparse extents | Before and during allocation |
141
+ | Cumulative emitted bytes | Shared counter across all entries |
142
+ | Entry count | Before accepting the next entry |
143
+ | Nesting depth | Before opening a nested container |
144
+ | Parser CPU and elapsed time | Whole extraction deadline |
145
+ | Temporary disk and files | Sandbox or quota boundary |
146
+
147
+ Reject symlinks, hardlinks, devices, FIFOs, absolute paths, traversal, alternate separators,
148
+ reserved names, and duplicate normalized destinations unless the product has a narrower explicit
149
+ contract. Do not trust declared uncompressed sizes; stop when actual emitted bytes exceed budget.
150
+
151
+ Reject case, Unicode, trailing-dot, trailing-space, short-name, and separator aliases under the
152
+ final consumer platform. Preserve the validated entry object through extraction so a second parser
153
+ cannot reinterpret the raw name. Accept regular files and directories only by default, use exclusive
154
+ creation below a root capability, and never merge into an existing or attacker-writable tree.
155
+
156
+ Do not restore archive uid, gid, owner names, original modes, setuid, setgid, sticky bits, ACLs,
157
+ xattrs, capabilities, or timestamps by default. Sparse entries require both logical-size and actual
158
+ storage budgets. Extract into a new private staging directory and publish only the verified tree.
159
+
160
+ Library path cleanup, extraction filters, or non-local-name warnings are versioned defense in depth.
161
+ Pin the runtime and API option, but keep the application entry, collision, metadata, capability,
162
+ and resource policies independent of the current library default.
163
+
164
+ Each extracted regular file re-enters filename, type, parser, authorization, and publication
165
+ checks. Nested containers consume the same parent budget. They do not get a fresh unlimited quota.
166
+
167
+ ## 6. Remote-fetch SSRF ledger
168
+
169
+ Arbitrary URL import combines network authority with the upload pipeline. Prefer provider-owned ids
170
+ or preconfigured integrations. If arbitrary URLs are necessary, record every decision:
171
+
172
+ | Phase | Required evidence |
173
+ | --- | --- |
174
+ | Parse | One strict parser result; no validate-with-one, connect-with-another split |
175
+ | Scheme and method | Small fixed allowlist, normally `https` and `GET` |
176
+ | Host | Canonical host and IDNA result; reject ambiguous userinfo and fragments |
177
+ | Port | Fixed or narrow allowlist |
178
+ | Resolve | Every A and AAAA result plus relevant CNAME outcome |
179
+ | Address policy | Normalized IPv4, IPv6, and mapped-address classification |
180
+ | Connect | One validated address bound to the socket |
181
+ | TLS and HTTP | Canonical hostname retained for certificate and host semantics |
182
+ | Redirect | Every hop reparsed, resolved, classified, and budgeted |
183
+ | Headers | No inbound auth, cookies, proxy credentials, or arbitrary user headers |
184
+ | Egress | Network firewall or proxy independently blocks forbidden ranges |
185
+ | Response | Header, body, decoded-work, connect, read, and total deadline limits |
186
+ | Handoff | Response enters quarantine as a new hostile upload |
187
+
188
+ Reject loopback, private, link-local, multicast, unspecified, reserved, and infrastructure metadata
189
+ destinations according to deployment policy. Check both address families. A hostname with one public
190
+ and one forbidden result is not safely public just because the first answer looked acceptable.
191
+
192
+ Disable redirects by default. When enabled, cap hop count and treat each `Location` as fresh input.
193
+ Do not let a generic HTTP client silently re-resolve or follow a proxy path that bypasses the
194
+ validated address.
195
+
196
+ ## 7. Parser sandbox and capability matrix
197
+
198
+ For each native tool, library, delegate, or subprocess, record:
199
+
200
+ | Capability | Policy question |
201
+ | --- | --- |
202
+ | Input formats | Which coders or parsers are enabled? |
203
+ | Delegates | Can input launch another interpreter or executable? |
204
+ | Filesystem read | Can it read outside the isolated input directory? |
205
+ | Filesystem write | Can it write outside bounded temporary and output directories? |
206
+ | Network | Is outbound access disabled by runtime policy? |
207
+ | Processes | Can it spawn children, and how many? |
208
+ | Privilege | Which user, group, namespace, or container runs it? |
209
+ | Resources | CPU, memory, map, disk, files, descriptors, threads, wall time, output |
210
+ | Failure | What happens on crash, timeout, truncation, or partial output? |
211
+ | Version | Which tool and security policy version made the decision? |
212
+
213
+ An application timeout without process termination is incomplete. Cancellation must stop child
214
+ work, close streams, prevent publication, and clean bounded temporary artifacts.
215
+
216
+ ## 8. Resource, concurrency, and cost budget
217
+
218
+ Build one budget ledger from edge to worker instead of isolated `10MB` checks:
219
+
220
+ - wire bytes: request body, file, multipart overhead, chunks, remote response;
221
+ - structure: files, archive entries, pages, frames, layers, tracks, nodes, relationships;
222
+ - decoded work: pixels, samples, decompressed bytes, parser tokens or objects;
223
+ - runtime: CPU, memory, temporary disk, descriptors, processes, threads, elapsed time;
224
+ - outputs: thumbnails, previews, rewritten objects, extracted files, logs, metadata;
225
+ - concurrency: per-user, per-tenant, per-worker, global in-flight jobs, queue depth;
226
+ - retries and lifecycle: attempts, total age, stale partials, cleanup backlog;
227
+ - durable cost: storage bytes, CDN bytes, scanner calls, OCR pages, transcode minutes.
228
+
229
+ Define reservation and release points. A quota checked after expensive conversion or after object
230
+ storage has already grown is accounting, not prevention.
231
+
232
+ ## 9. Layer responsibility handoff
233
+
234
+ Keep every layer honest about what it can prove:
235
+
236
+ | Layer | Owns | Does not prove |
237
+ | --- | --- | --- |
238
+ | Frontend | Early feedback, picker hints, progress | Security or final type |
239
+ | Edge/proxy | Wire envelope, coarse rate and timeout | Parser semantics |
240
+ | Upload API | Strict multipart syntax, auth, quarantine identity | Safe derived output |
241
+ | Domain service | Allowed use, owner, state transition, publication policy | Native parser isolation |
242
+ | Storage | Immutability, versioning, conditional writes, retention | Content safety |
243
+ | Worker | Exact-version parsing, budgets, derived output, result evidence | Download authorization |
244
+ | Database | Constraints and atomic state transitions | Object bytes by itself |
245
+ | Serving layer | Current authorization, headers, origin, exact approved object, immutable asset manifest | Prior client checks or path-prefix ownership |
246
+
247
+ Queue consumers must revalidate durable facts. A queued message carrying `approved = true` is not a
248
+ substitute for loading current state and the immutable object identity.
249
+
250
+ For downloads, resolve authorization before the exact object key, treat `Content-Disposition`
251
+ filenames as presentation, remove CR/LF and path components, and generate a conservative ASCII
252
+ `filename` fallback plus a correctly encoded UTF-8 `filename*`. Never reuse either header value as a
253
+ storage locator. Serve built assets through an immutable URL-to-asset manifest; a SPA fallback should
254
+ return one fixed `index.html` only after route classification, not probe alternate filesystem names.
255
+
256
+ Escape control characters in rejected filenames before logging. Store a bounded display value and a
257
+ stable policy code rather than allowing raw names to forge log lines.
258
+
259
+ ## 10. Denial and differential test matrix
260
+
261
+ Use safe synthetic fixtures. Cover at least the paths present in the product:
262
+
263
+ - extension, request MIME, signature, and structural parser disagree;
264
+ - image dimensions, frames, layers, or metadata exceed cumulative budgets;
265
+ - document page or object counts exceed policy before unbounded rendering;
266
+ - archive traversal, absolute path, alternate separator, duplicate normalized name, symlink,
267
+ hardlink, device, FIFO, file-directory prefix conflict, order-dependent link, metadata restore,
268
+ sparse logical-size overflow, false size header, nested-budget exhaustion;
269
+ - parser timeout, crash, partial output, unavailable scanner, and cancellation;
270
+ - quarantine object replaced between upload and inspection or inspection and promotion;
271
+ - promotion reads latest generation instead of the recorded immutable version;
272
+ - hostname resolves to mixed public and forbidden addresses;
273
+ - redirect changes scheme, port, host, address class, or exhausts the total budget;
274
+ - DNS re-resolution or proxy routing chooses a different address than the validated one;
275
+ - inbound credentials or cookies would be forwarded to a remote target;
276
+ - remote response passes network policy but fails ordinary upload type or parser policy;
277
+ - rejected or failed files remain unavailable through download, preview, CDN, email, admin, search,
278
+ and derived-object paths.
279
+ - public path or prefix input cannot bypass opaque-id authorization and exact-version lookup;
280
+ - `Content-Disposition` CR/LF and path fragments cannot alter headers or storage lookup;
281
+ - static extension probing and raw-name log injection are rejected.
282
+
283
+ Where two detectors or parsers exist, add differential fixtures so disagreement is an explicit
284
+ failure or policy branch rather than an accidental first-match winner.
285
+
286
+ ## 11. Primary reference anchors
287
+
288
+ Use current primary documentation when refreshing claims:
289
+
290
+ - OWASP File Upload Cheat Sheet for defense-in-depth upload controls, generated names, storage
291
+ placement, type signals, size limits, scanning, CDR, and archive expansion limits.
292
+ - OWASP SSRF Prevention Cheat Sheet for URL allowlisting limits, redirect control, scheme policy,
293
+ DNS pinning checks, and A/AAAA review.
294
+ - OWASP API Security API4 for memory, CPU, file descriptor, process, upload, operation-count, page,
295
+ and third-party spending limits.
296
+ - ImageMagick security policy documentation for coder, delegate, path, memory, map, disk, file,
297
+ thread, time, width, height, and list-length controls when ImageMagick is in the parser path.
298
+ - Go `os.Root` and Java `SecureDirectoryStream` official documentation for root-relative runtime
299
+ capabilities and their platform or provider limits.
300
+ - Python `tarfile` and `zipfile`, plus Go `archive/zip`, for versioned extraction filters, caller-owned
301
+ path validation, special entry metadata, sparse members, and non-local-name diagnostics.
302
+ - RFC 6266 for treating response filenames as advisory presentation values and handling path
303
+ components, control characters, device names, `filename`, and `filename*` safely.
304
+
305
+ External guidance is a floor. The repository's concrete parser, object-storage, network, tenant,
306
+ and serving contracts decide the actual implementation and test evidence.