A file's name says nothing about its content
You can rename malware.exe to invoice.pdf with two clicks. The extension is metadata — an arbitrary label — while the file's actual format is determined by its bytes. Operating systems hide extensions by default, which makes it trivially easy to send someone a disguised file that looks like a document in an email or a chat app.
Fortunately, almost every file format starts with a predictable byte pattern called a file signature — informally, magic bytes. Read those first few bytes and the file tells you what it really is.
Famous magic bytes you can learn by heart
| Signature (hex) | File type | Why you recognize it |
|---|---|---|
FF D8 FF | JPEG image | Starts with the "JPEG SOI" marker |
89 50 4E 47 0D 0A 1A 0A | PNG image | The infamous ‰PNG opening |
47 49 46 38 | GIF image | ASCII GIF8 |
25 50 44 46 2D | PDF document | ASCII %PDF- |
50 4B 03 04 | ZIP archive | Also .docx, .xlsx, .jar, .apk — they are all ZIPs |
D0 CF 11 E0 A1 B1 1A E1 | Legacy Office | Old .doc / .xls binary format |
7F 45 4C 46 | Linux executable (ELF) | DEL + ELF |
4D 5A | Windows executable | ASCII MZ — Mark Zbikowski, the DOS developer |
1F 8B | gzip archive | Compressed Linux downloads |
52 49 46 46 | RIFF container | WAV and AVI files |
42 4D | BMP image | ASCII BM |
The 50 4B 03 04 ZIP signature explains a useful trick: a .docx that "won't open" can often be unzipped manually — because it is a zip file containing XML.
How signature detection works
A detector reads the file at offset 0 and compares the leading bytes against a table of known signatures. In JavaScript it is a few lines over an ArrayBuffer:
const buf = await file.slice(0, 16).arrayBuffer();
const bytes = new Uint8Array(buf);
if (bytes[0] === 0x89 && bytes[1] === 0x50) console.log('PNG');
if (bytes[0] === 0xFF && bytes[1] === 0xD8) console.log('JPEG');
if (bytes[0] === 0x25 && bytes[1] === 0x50) console.log('PDF');
Some formats hide their signature at a fixed non-zero offset — e.g. disk images or some container formats mark their header a few hundred bytes in — so robust inspectors check a small set of known offsets and use content heuristics (like UTF-8 validation for text formats) as a fallback. That is exactly what the File Signature Inspector does: it reads the header locally in your browser, decodes the signature, and tells you the most likely true format.
Sponsored
Why this matters for security
Attack 1 — the spoofed extension. Email attachment: Report.pdf whose signature is 4D 5A — a Windows executable. The PDF reader association never gets involved because there is no PDF inside. Users who "always open PDFs" never see it coming.
Attack 2 — the polyglot file. Crafted files that are valid in two formats at once — a file that is both a harmless GIF to the image validator and a PHP script to the server. Signature checks at offset 0 alone can be fooled by polyglots; that is why upload pipelines layer checks (see below).
Attack 3 — the renamed upload. A web app that validates uploads by extension only will happily accept payload.exe renamed to payload.png — and then serve it. If the server also declares it image/png while the bytes are an executable, extension-based "validation" has achieved nothing.
A defense-in-depth upload checklist
If you run any app that accepts uploads, validate in this order:
- Size limit first — cheap DoS protection before any parsing happens.
- MIME type from content, not from the client-supplied header: read the magic bytes with the MIME Detector logic (server-side) or a library.
- Signature check for the exact expected type — a PNG must start with
89 50 4E 47, not merely "look like an image". - Re-encode the image if applicable (ImageMagick, sharp) — this destroys polyglot payloads by rewriting every pixel.
- Serve uploads safely: never as
text/html, ideally from a sandboxed domain, withX-Content-Type-Options: nosniff. - Checksum the stored file with the File Checksum tool so its integrity can be verified later.
Inspecting a suspicious file in 30 seconds — safely
The golden rule: do not open the file with its default application. Instead:
- Open the File Signature Inspector.
- Drop the file in. Everything is read locally by your browser — the file never touches a server, so even genuinely malicious files cannot execute (a browser reading bytes is not an execution context).
- Read the verdict: the detected signature and true format.
- Cross-check with the MIME Detector and, for images, peek at embedded location and camera data with the Image Metadata Viewer.
If invoice.pdf turns out to start with 4D 5A, delete it — and if it arrived by email, report it. The magic bytes never lie, because unlike the filename, nobody thought to forge them.
Related free tools
Try these free online tools — all run in your browser with no sign-up.
Keep reading
More hand-written guides from the blog.