An uploaded file crosses from a caller's device into storage the application controls. Its filename and declared media type, such as image/jpeg, are claims supplied with the upload. A media type describes a format; it does not prove that the submitted bytes form a valid file of that format.
A file signature is a recognizable byte sequence associated with a format. It can support a hypothesis, but a complete valid image also needs the rest of its required structure. The supplied eight-byte fixture deliberately contains only a signature. No image parser has confirmed a complete image.
Before you begin
- Recommended first
- Notes: scope, command, result, time, HTTP methods, headers, status codes, cookies, How a web app is put together, Same-origin policy, Access control and IDOR
- Estimated time
- 16 min reading, 12 min activity. Setup and optional practice may take longer.
- Where you work
- Read the original fictional requests, source fragments and state tables in a current desktop or mobile browser. The required activity needs no server, database, account or installed security tool. Do not send the printed requests to any service.
- Without a lab
- Use the complete printed evidence to trace the data or state on paper. Write the decision, the fact supporting it and one limit of the model, then compare with the activity rubric. This does not establish live service behavior. Reading works without JavaScript. Checking requires JavaScript and a secure browser context; saving also requires usable browser storage.
After this lesson you can:
- Separate a filename, a declared media type, and the bytes.
- Read the activity bytes 64 65 73 6B as letters.
- Pick the storage card that keeps an upload out of the executed directory.
01Example
The fictional file note.jpg claims image/jpeg, but its five bytes are ordinary text. Use ASCII to interpret the evidence before trusting the name.
Claimed name: note.jpg
Claimed media type: image/jpeg
Bytes: 68 65 6C 6C 6F
Text interpretation: hello
The claim does not match the contents.02Claims, bytes, and a place to put them
The worked bytes spell hello, even though the filename claims an image. The guided activity uses different text bytes. Compare the claim with the actual byte evidence before judging storage policies. The checkpoint supplies a separate signature-only file; name the format suggested by that evidence, without claiming the whole file is valid.
Upload handling needs several controls: allow only required types, validate content with appropriate tooling, limit size and decompression work, and keep uploads outside executable application paths. S1 addresses the execution boundary in this model. Type validation and safe storage have different jobs; neither filename nor declared type is enough.
Compare a filename and a declared type with the bytes, and store an upload outside the directory the server runs as code.Model. A teaching model drawn by hand. It shows the idea, not real tool output.
Read the full explanation below.
Playback is optional. Step through at your own pace.
Supplied upload claims
note.jpgfilename claimimage/jpegmedia claimSupplied bytes
68 65 6C 6C 6Ffive bytesThese five bytes are supplied; no image decoder ran.Text interpretation
helloASCII readingnote.jpg + image/jpeg → 68 65 6C 6C 6FClaims differ from contents
Filename and media type are caller claims.
Follow the explanation
- Filename and media type are caller claims.
- The supplied bytes read hello, which does not establish a JPEG.
Read every state and value
1. Filename and media type are caller claims.
- Example
- Supplied teaching sample
- Visible Item
- note.jpg · image/jpeg · 68 65 6C 6C 6F
- Current mappings
- Claims differ from contents
- Annotations
- Item: 68 65 6C 6C 6F; Text: These five bytes are supplied; no image decoder ran.
2. The supplied bytes read hello, which does not establish a JPEG.
- Example
- Supplied teaching sample
- Visible Item
- note.jpg · image/jpeg · 68 65 6C 6C 6F · hello
- Current mappings
- Supplied ASCII interpretation · Claims differ from contents
- Annotations
- None
03Read the activity bytes
Read the evidence before comparing your reasoning with the activity rubric. Do not run an image parser.
PNG signature from the PNG specification, section 5.2, eight bytes:
89 50 4E 47 0D 0A 1A 0A
benign-mislabeled.jpg contains only those eight bytes.
It has no IHDR chunk and no IEND chunk, so it is not a complete PNG datastream.
No image parser was run. The filename and the declared type are claims.
Worked card
filename: note.jpg
declared: image/jpeg
bytes: 68 65 6C 6C 6F
ASCII from Stage 04: hello
The bytes are letters.
Activity card
filename: badge.jpg
declared: image/jpeg
bytes: 64 65 73 6B
ASCII: desk
The bytes are letters.
Field card
filename: image.jpg
declared: image/jpeg
bytes: 89 50 4E 47 0D 0A 1A 0A
Compare these bytes with the reference signature and state what format they suggest. A signature match alone does not establish a complete valid image.
Upload storage cards. Pick the card that matches the stated goal.
S1 Store the bytes outside the directory that the server executes as code.
S2 Trust the filename suffix and store the file beside the application.
S3 Trust the declared media type and display the file as that type.
The goal in this lesson is to keep an upload from becoming a program the server runs.
S1 matches that goal. S2 and S3 trust a claim.
- Read the activity card. Write the filename, the declared type, and the bytes.
- Use the Stage 04 reading of those bytes.
- Check: the bytes are the letters desk. They are not the eight-byte signature. S1 is the storage card that matches the goal. The worked bytes are hello.
- Stop. Do not upload this file to a real application.
04Optional challenge
Say why S1 matches the goal and S2 does not. The rubric is: S1 moves the bytes out of the executed directory, and S2 trusts the suffix. About ten minutes.
05Fresh cases for the checks
Use these fictional cases for the checks below. They have different inputs from the worked examples. Read them here or make notes; no installation or external service is needed.
Upload case A: signature comparison, no parser runOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
PNG reference signature: 89 50 4E 47 0D 0A 1A 0A.
Candidate filename: letter.txt; declared media type: text/plain.
Candidate bytes: 89 50 4E 47 0D 0A 1A 0A, and nothing else.
No image chunks or parser result are supplied.
Upload case B: independent text bytesOwned fixture. An original file made for this course. Follow the activity's instructions in your own lab.
Filename: sketch.jpg; declared type: image/jpeg.
Bytes: 6F 61 6B
Supplied ASCII map: 6F=o, 61=a, 6B=k.
These are all the bytes; no decoder or parser is run.
06Explain your evidence
Optional written self-check: explain one decision using the supplied case. No tool run is required.
Check your explanation: compare claims with supplied bytes; distinguish a matching signature from a complete parser-accepted file; trace the ASCII map; connect upload storage to the server execution boundary.
07Common mistakes
If you call the activity bytes an image because the name ends in jpg, you trusted the claim. The bytes are letters.
If you call the eight-byte file a complete image, you skipped the missing IHDR and IEND. The signature is only the first eight bytes of a datastream.
If you pick S3 because the declared type says image, you trusted the claim the card warns about.
References
- PNG Specification (Third Edition), section 5.2
W3C Recommendation of 24 June 2025, read. The first eight bytes are 89 50 4E 47 0D 0A 1A 0A. The signature indicates that the remainder is a single PNG image of chunks from IHDR to IEND. The fixture is only those eight bytes, so it is not a complete PNG.
- PortSwigger: File upload
Explains the failure mechanism and prevention. Use it for further reading after reasoning from this page's original model; a topic page is not evidence that a lab was launched.