Magic bytes vs file extensions

An extension is a claim. Magic bytes are evidence. Neither one is proof.

By Ihor Havrysh ยท Last reviewed July 2026

Eaglepedia mascot

Magic bytes, also called a file signature, are the short sequence of bytes at the start of a file that identifies its format. Checking them tells you what a file's contents claim to be, whereas a file extension only tells you what its name claims. Neither is proof of what the file will do.

An extension is just part of the name

A file extension has no authority over what a file contains. It is a convention that helps operating systems pick a default application, and it is a few characters at the end of a string that whoever uploaded the file chose freely.

Rename a document to end in .png and nothing about it changes. The bytes are identical. Any check that reads the name and concludes something about the contents has confused a label with the thing it labels.

That does not make extension checks worthless. Checking against a list of permitted extensions is cheap, runs before you have read the file, and lets you return an error a user can understand. PortSwigger's own guidance is to check extensions against a list of permitted types rather than a list of prohibited ones, because an allowlist fails closed when something unexpected turns up while a blocklist fails open. The OWASP File Upload Cheat Sheet takes the same position. Keep the check. Just be clear that it filters intent rather than establishing fact.

Magic bytes read the file itself

Most binary formats begin with a distinctive marker so that software can recognise them without relying on a filename. A PNG opens with an eight-byte header chosen partly to survive being mangled by file transfers. A PDF opens with a percent sign, the letters PDF and a version. A ZIP archive, and therefore every modern Office document, opens with the letters PK, after the format's original author.

Reading those bytes and comparing them against a database of known signatures is how the Unix file command and the libmagic library identify formats, and it is what most languages' file type detection is doing underneath. The improvement over an extension check is real, because you are now looking at the contents rather than the label.

Two files with the identical name photo.png, one opening with PNG signature bytes and the other with executable bytes
Same name, different file. Only one of the two checks involves opening anything.

Two limits are worth knowing. Text-based formats often have no signature at all, so an SVG, a CSV or a JSON file gives you very little to match on. That is one reason SVG uploads need handling on their own terms, and why a CSV export can carry a formula rather than data without anything looking wrong. And a signature match tells you the file starts correctly, which is a statement about its first few bytes rather than about all of it.

There is a matching problem on the way back out. Declaring the right content type when you serve a file only helps if the browser honours it, and by default it may not: see MIME sniffing.

Where both checks stop

Here is the ceiling, and it is worth understanding before you conclude that magic bytes have solved the problem.

A polyglot file has correct magic bytes. That is the entire design. It begins as a genuine image so that content validation accepts it, while also containing a region that another parser reads as its own format. Your check is not being deceived by a forged signature; the signature is real, and the check is answering a narrower question than you were asking.

Nor do magic bytes say anything about what happens when the file is processed. A structurally perfect ZIP archive can be a zip bomb. A structurally perfect Office document can contain a macro. In both cases the format is exactly what it claims, and the risk lives in what the file asks software to do afterwards.

So the honest summary of the ladder is:

Check What it establishes What defeats it
Content-Type header What the client said the file is Editing the request
File extension What the filename claims Renaming the file
Magic bytes The file genuinely starts as that format A polyglot, whose start is genuine
Full parse and rebuild What survives is content you chose to keep Nothing structural, though it changes the file

The order worth implementing

Each rung earns its place by closing the bypasses the one below it allows, so the sensible approach is to run them in sequence and stop as soon as something fails.

  1. Extension against an allowlist. Cheap, fast, and produces an error message the user can act on
  2. Magic bytes. Confirms the contents match the claim, and rejects the straightforward mismatches
  3. Parse or rebuild. Re-encode images from their decoded pixels, and put documents through content disarm and reconstruction. This is the only step that reads the whole file rather than its opening bytes

Alongside those, treat the Content-Type header as a hint about intent and never as a control, and keep the structural protections in place regardless: rename files, store them outside anywhere the server would execute them, and serve them from a separate origin. Those hold even on the occasion validation is wrong, which is the property that matters most.

Our guide to file upload security covers how these fit together in a complete pipeline.

Checking the first bytes is necessary. Reading the whole file is the part that decides. The Red Eagle Tech CDR API rebuilds a document from the components that carry legitimate content, so what you store is defined by what you kept rather than by what you managed to spot. Published per-document pricing, and you can be running in minutes.

Frequently asked questions

They are the short, fixed sequence of bytes at the beginning of a file that identifies its format. A PNG starts with a distinctive eight-byte header, a PDF begins with a percent sign followed by PDF and a version number, and a ZIP archive starts with the letters PK. Utilities such as the Unix file command and the libmagic library work by matching these patterns against a database of known signatures.

As a first filter, yes, and it is worth keeping. Checking the extension against a list of permitted types rejects obviously unwanted uploads cheaply and tells the user something useful. The mistake is treating it as validation. The filename is chosen by whoever uploads the file, so it is a claim about the file rather than evidence about it.

They cannot be faked exactly, because a correct signature means the file genuinely starts the way that format starts. What they can be is insufficient. A file can carry a legitimate signature and still contain something else further in, which is precisely how a polyglot file works. The check is honest about the beginning of the file and says nothing about the rest.

It is the weakest of the three, because it is supplied by the client and never derived from the file at all. PortSwigger's guidance is blunt that where a server implicitly trusts this header without checking the contents match, the defence is easily bypassed with an intercepting proxy. Use it as a hint about intent, never as a control.

Extension against an allowlist first, because it is cheap and gives a clear error. Then magic bytes, to confirm the contents match the claim. Then full parsing or reconstruction, because that is the only step that inspects the whole file rather than its first few bytes. Each rung closes bypasses the previous one allowed, and the last one is the only one that reaches the end of the file.
Ihor Havrysh - Software Engineer at Red Eagle Tech

About the author

Ihor Havrysh

Software Engineer

Software Engineer at Red Eagle Tech with expertise in cybersecurity, Power BI, and modern software architecture. I specialise in building secure, scalable solutions and helping businesses navigate complex technical challenges with practical, actionable insights.

Read more about Ihor

Discovery call

A friendly 15-minute video call with Kat to understand your needs. No preparation needed.

  • Discuss your project
  • Get honest advice
  • No obligation
Kat Korson, Founder of Red Eagle Tech

Kat Korson

Founder & Technical Director

Our team has 10+ years delivering software solutions for growing businesses across the UK.

Send us a message

Your information is secure. See our privacy policy.

Find us