BUG BOUNTYFIELD MANUAL
Reusable module
Markdown
0 / 7 checkedChecks last until this page reloads.

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. 01Map file lifecycle
  2. 02Seed harmless canaries
  3. 03Change one file property
  4. 04Check parser and destination
  5. 05Verify another controlled reader
  6. 06Remove every derivative

At each step: retain the control → record the observation → continue only while the next boundary is understood.

Used in these playbooks#

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.

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.
  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.
  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.

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.

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.

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

Vulnerability reverse references#

Nearby shared procedures#

Object, function, and property authorization · Authentication, recovery, federation, and session lifecycle · Trace input into queries, commands, and templates · Server-side fetching and network trust boundaries · Browser execution, cross-origin reads, and forged actions · Workflow invariants, replay, idempotency, and races · REST, GraphQL, gRPC, WebSocket, and SSE permission parity · Proxy normalization, cache isolation, and request boundaries