# Uploads, downloads, paths, archives, and XML

Follow a file through acceptance, storage, processing, publication, and retrieval while preserving ownership and path boundaries.

## Investigation sequence

1. Map file lifecycle
2. Seed harmless canaries
3. Change one file property
4. Check parser and destination
5. Verify another controlled reader
6. Remove every derivative

## Used in these playbooks

[Web & API](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/web-api.html) · [OSS & self-hosted](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/oss.html) · [Desktop & extensions](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/desktop.html) · [Mobile](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/mobile.html) · [AI, agents & MCP](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/ai.html) · [Cloud & containers](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/cloud.html)

### Setup and invariant

Use a local replica, a tiny supported file, two controlled accounts, and a dedicated scratch directory. Identify upload handler, object store, converter, background worker, CDN/download route, and deletion path. Place a unique harmless canary just outside the permitted download root, through normal local filesystem access. The invariant is: **user-controlled file metadata or contents cannot escape storage, interpretation, or ownership rules**.

Separate filename, MIME declaration, actual bytes, storage key, filesystem path, and retrieval origin. Each component may normalize them differently. Acceptance of an unusual extension alone does not prove unsafe execution. [Upload handling](https://portswigger.net/web-security/file-upload).

### Numbered test procedure

1. **Record a supported baseline.** Upload a tiny text/image fixture through the documented route. Save its object ID, resulting filename, declared and detected type, processor status, retrieval headers, and response bytes. Verify A can retrieve it and B cannot when the file is private.
2. **Change one property.** Resubmit the same harmless content with a different filename or MIME declaration, independently. For a type-restricted image endpoint, text labeled `image/png` should either fail or be safely handled. Inspect the stored result and actual browser rendering. Do not upload executable shells or server configuration files to demonstrate an extension mismatch.
3. **Check path containment.** In the local replica, request the planted out-of-root marker using one relevant `../` path. Compare a valid in-root file and a nonexistent sibling path. Preserve the raw request target and server-resolved path; a client or proxy may normalize dot segments before they reach the application. If testing writes, use only a dedicated disposable output directory and check that an outside marker is not created. [Path traversal](https://portswigger.net/web-security/file-path-traversal).
4. **Check ownership through derivatives.** As B, request A's controlled original, thumbnail, conversion result, archive export, and any observed signed URL. Record whether the URL is intentionally a share capability and its documented lifetime. Deleting the primary record does not prove every derivative became inaccessible; evaluate the product's promised behavior.
5. **Check archive and XML processing locally.** For an extractor, create a tiny archive with one ordinary member and one canary path outside its designated extraction directory; inspect resolved paths without overwriting anything important. For an XML parser, compare a plain literal field with one external entity referencing the controlled HTTP canary from the SSRF module. Correlate callback logs and returned marker. Do not use recursive entities, oversized documents, or operating-system files. XML acceptance or a DOCTYPE error alone is not external-entity resolution. [XXE](https://portswigger.net/web-security/xxe).
6. **Interpret downstream effects.** Wait for the single test job to finish. Compare bytes, filesystem location, ownership, browser origin, and any parser callback. Source review should locate the exact join/extraction/parse operation and whether containment checks occur after normalization. Delete originals, derivatives, exports, and queued test jobs.

### Command card

This creates a local download fixture. Configure the replica's allowed download directory as `file-lab/public`; illustrative endpoint and parameter names must match the application.

```bash
mkdir -p file-lab/public evidence/files
printf '%s\n' 'BB-INSIDE-01' > file-lab/public/inside.txt
printf '%s\n' 'BB-OUTSIDE-01' > file-lab/outside.txt
curl -q --noproxy '*' --max-time 10 --get --header @A.header \
  --data-urlencode 'name=inside.txt' \
  -o evidence/files/baseline.txt \
  http://127.0.0.1:8000/api/download
curl -q --noproxy '*' --max-time 10 --get --header @A.header \
  --data-urlencode 'name=../outside.txt' \
  -o evidence/files/traversal.txt \
  http://127.0.0.1:8000/api/download
```

### Report threshold and checklist

Report a proven outside-root read/write, unauthorized controlled-file access, unsafe browser/server interpretation, or prohibited parser fetch. A reflected filename, harmless stored extension, public sharing by design, and asynchronous rejection are frequent false positives.

- [ ] Upload and retrieval rules documented independently.
- [ ] Only tiny, synthetic files and dedicated canaries used.
- [ ] Filename, MIME, contents, and ownership varied separately.
- [ ] Raw request and resolved destination retained.
- [ ] Processed derivatives included in evidence and cleanup.

Local curl examples bypass environment proxies with `--noproxy '*'`; `-q` alone only suppresses curl configuration files. These snippets target loopback and do not follow redirects. [curl manual](https://curl.se/docs/manpage.html).


### Containment beyond dot segments

For a link-capable filesystem or archive format, test a tiny symbolic-link fixture in the disposable directory as a separate case. Point it only to the already-planted harmless outside canary, then exercise the product's real reader/extractor. Record the final resolved destination and the identity that opened it. A lexical `..` rejection does not establish containment when links, absolute member paths, platform separators, or case collisions change the destination. Do not generalize a local administrator-created link into a remote vulnerability: show how the stated attacker can create or influence that link through the product.

Pin the runtime and actual extraction API/filter. Python's tar extraction filters can reject outside destinations and links, but filter availability, explicit overrides, and additional resource limits matter. A failed extraction may also leave earlier members on disk; inspect and remove only the disposable output. If a TOCTOU claim depends on replacing a path between validation and opening, demonstrate that timing separately in the replica; a static link test does not prove a race. [Python extraction filters and limitations](https://docs.python.org/3/library/tarfile.html#extraction-filters).

- [ ] Final resolved file or link target stays inside the intended root.
- [ ] Actual runtime/filter and partial-extraction cleanup documented.


## Vulnerability reverse references

- [Reflected or stored cross-site scripting](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/xss-reflected-stored-origin-execution.html) — Attacker-controlled input executes in another controlled user’s browser under the application origin.
- [Unsafe upload interpretation or placement](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/unsafe-upload-interpretation.html) — Uploaded content is handled in a security-sensitive context beyond its permitted file contract.
- [Path traversal outside an allowed root](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/path-traversal-controlled-canary.html) — A controlled path escapes the intended filesystem or object-key boundary.
- [XML external entity injection (XXE)](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/xxe-external-entity-resolution.html) — An XML parser resolves untrusted external entities across an unintended file or network boundary.
- [Archive extraction path escape](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/archive-extraction-path-escape.html) — An archive member is extracted outside its designated output directory.
- [Content-provider permission or URI-grant escape](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/android-provider-grant.html) — A recipient obtains data or file capabilities beyond the URI and permissions deliberately shared with it.
- [Extension input crosses an iOS shared-container boundary](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/ios-shared-container-trust.html) — The main application trusts content written through a lower-trust extension/input path as if it were an authorized app action.
- [Desktop protocol handler misinterprets external input](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/desktop-protocol-confusion.html) — An OS-dispatched URL reaches a native command or operation with attacker-controlled arguments outside the intended handler contract.
- [Privileged updater consumes lower-user-controlled staging content](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/updater-privileged-staging.html) — A standard user can replace a staged file or redirect a path actually consumed by a privileged installation process.
- [Sensitive data in errors, debug routes, or generated files](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/sensitive-error-disclosure.html) — An error or debug output crosses a confidentiality boundary by revealing protected state.
- [Encrypted data accepted without integrity authentication](https://bug-bounty-field-manual.kmahshooq.chatgpt.site/vulnerabilities/crypto-authentication-missing.html) — A protected data format permits security-relevant changes that are not detected before use.
