There’s a running joke in computing that DOOM will eventually run on everything. Not as a boast about the game, but as a challenge: the 1993 shooter has been made to run on cash machines, printers, pregnancy tests, calculators, a single LEGO brick and the touch bar of a MacBook.
In January 2025 a high-school student added a new one to the list. They got DOOM running inside a PDF file.

The short version
A high-school student compiled DOOM to asm.js with a 2020-era version of Emscripten and ran it inside a PDF, using one form field per screen row as a display: 320×200, six shades of grey, about 80 milliseconds a frame. No vulnerability was involved. Every feature it uses is a documented part of the PDF specification, working as designed. That is the interesting part — and the reason a document is worth ten minutes of your attention, once.
It’s a wonderful piece of work and a very good joke. It’s also the single clearest demonstration of something this site keeps arguing, and which people reasonably find hard to believe: a PDF is not a picture of a page. It’s a container that can run code.
How it actually works
The project is called doompdf, by a developer who goes by ading2210. The mechanism is more interesting than the stunt, and it has four parts.
PDF supports JavaScript. Not as an add-on or a plugin — it’s part of the format, with its own standard library, and browsers implement it in their built-in PDF engines. It exists so that forms can validate what you type and interactive documents can respond to clicks. Nobody added it for games.
DOOM’s source code is public — though the history is more particular than the shorthand suggests. id Software released the code on 23 December 1997, but under a licence that permitted educational use only, and the release was of the Linux port rather than the DOS original, because of the DMX sound library’s separate licensing. The GPL relicence came almost two years later, on 3 October 1999. That second date is the one that matters: it turned DOOM from something you could read into something you could legally rebuild, which is why the game keeps turning up in unlikely places.
The two were bridged with a deliberately obsolete compiler. ading2210 used Emscripten 1.39.20 — a version from 2020 — because it targets asm.js rather than WebAssembly. Modern Emscripten produces WebAssembly, and a PDF has no WebAssembly runtime. asm.js is a restricted dialect of plain JavaScript, so it runs anywhere JavaScript runs. Choosing the older toolchain was not nostalgia; it was the only way in.
Then there’s the display, which is the part that makes people laugh out loud. A PDF has no canvas, no framebuffer, nothing to draw pixels on. What it does have is form fields. So the game’s 320×200 output is rendered as ASCII characters — one text field per row of the screen, in six shades of grey — and refreshed sixty-odd times as fast as the text can be rewritten, which works out at roughly 80 milliseconds per frame. Input arrives the same way, through fields and buttons the PDF engine already knows how to handle. You are, quite literally, playing DOOM in a fillable form.
It runs slowly. It’s monochrome. It’s completely playable, it’s released under the GPL v2 like the code it’s built on, and you can try it yourself in a Chromium-based browser. The build even lets you drop in your own WAD file.
Then he ran Linux in one
A few weeks later the same developer published linuxpdf: a full Linux kernel booting inside a PDF file, by compiling the TinyEMU RISC-V emulator with the same asm.js trick. The kernel takes 30 to 60 seconds to come up — the author puts it at over a hundred times slower than real hardware — and you drive it with a virtual keyboard built out of PDF buttons.
DOOM in a document is a joke. An emulated CPU booting an operating system in a document is an argument. Somewhere between the two, the point stops being about DOOM at all.
The part that isn’t funny
Here’s the thought worth sitting with. Nothing in doompdf is an exploit. No vulnerability was found, nothing was broken, no security hole was involved. Every single thing it uses is a documented, intended feature of the PDF specification, working exactly as designed.

Which means the capability that lets a PDF run a 1993 first-person shooter is present in the invoice you’ll open tomorrow. Not lurking, not hidden — just there, unused, because most documents have no reason to use it.
That is the honest version of the story, and it cuts both ways. The same reasoning that says “a document can run code, so be careful” also has to admit how narrow that code’s world is.
What a script in a PDF can and cannot do
This is where most coverage of doompdf goes vague, so it’s worth being specific. The answer depends entirely on what you opened the file in — and the two common cases are very different.
| Capability | Browser viewer (Chrome, Edge, Firefox) | Adobe Acrobat Reader |
|---|---|---|
| Run script on open | Yes | Yes, unless disabled |
| Read and write form fields | Yes | Yes |
| Read your cookies or browser storage | No | Not applicable |
| Reach the HTML page around it (the DOM) | No | Not applicable |
| Make network requests | Very limited | Broader — this is where tracking pixels and NTLM-leak tricks have lived |
| Touch local files | No | Restricted, but a larger API surface |
| Launch external programs or attachments | No | Prompted, and historically the route used by malicious documents |
Read that table the right way round. In a browser, a scripted PDF is running in a small, boring box — no cookies, no storage, no access to the page around it. That is precisely why doompdf is a curiosity rather than an incident, and why “DOOM runs in a PDF” is not a reason to be afraid of PDFs.
The desktop reader is the interesting column. It has the full JavaScript API the specification describes, because it’s meant to run real business documents. That is the environment where a document can be told to phone home the moment it opens, to behave differently for different readers, or to ask you to open something it has been carrying along.
So: three things remain true regardless of viewer, and they’re the ones worth internalising.
- A PDF can carry instructions that execute the moment it opens, before you have read anything.
- A PDF can behave differently depending on which software opens it — the file you’re looking at is not necessarily the file your colleague is looking at.
- A PDF carries more than it shows: attachments, hidden layers, revision history and metadata you never meant to send.
None of that makes PDFs dangerous in any everyday sense. You will open dozens this month and every one will be fine. It does mean the mental model most of us carry — “it’s just a document” — is wrong in a way that occasionally matters.
The setting almost nobody knows about
The standard advice is “turn off JavaScript in your PDF reader”, and it’s good advice. It is also, on its own, incomplete — because most people no longer open PDFs in a PDF reader. They open them in a browser tab, and the browser has its own, separate switch.
Firefox ships with PDF scripting on. The preference is pdfjs.enableScripting in about:config; it was false up to Firefox 87 and has been true since Firefox 88. Firefox’s general javascript.enabled toggle does not touch it — the PDF viewer is a separate world with a separate setting.
Chrome and Edge don’t expose a dedicated PDF-scripting switch at all. Script in a PDF is governed by the JavaScript permission for the site the file came from, which you can turn off per-site in the address-bar controls, or globally at chrome://settings/content/javascript — a considerably blunter instrument.
Adobe Acrobat Reader has the switch everyone means: Preferences → JavaScript → Enable Acrobat JavaScript. This is the one worth unticking, because Acrobat is the reader with the large API, and almost nobody knowingly uses a scripted PDF in ordinary work.
The practical shape of this: turning it off in Acrobat and leaving the browser alone is a reasonable, proportionate choice. Believing you have turned it off everywhere, when you have only turned it off in Acrobat, is not.
What to do with this information
The practical response is small and worth the ten minutes.
Turn off JavaScript in your desktop reader. That’s Preferences → JavaScript in Acrobat Reader. It removes an entire category of risk and costs you nothing except, admittedly, the ability to play DOOM in a form field.
Keep the reader updated. Scripting is one route in. Flaws in the code that decodes fonts and images are another, and those are what updates fix — they are also, historically, the more common route.
Treat unexpected documents as unexpected. An invoice from a company you have never bought from deserves a moment’s thought, whatever format it arrives in. This is worth more than any setting.
Notice what all three have in common: none requires you to stop using PDFs, or to be suspicious of documents generally. They’re the equivalent of locking your front door — cheap, boring, and sensible precisely because the risk is small but non-zero.
Why this project deserves the attention it got
It would be easy to file doompdf under “internet curiosity” and move on. I’d argue it’s more useful than that, for a reason that has nothing to do with security theatre.
Most people’s understanding of file formats is built entirely on what the formats are used for. Documents are for reading. Spreadsheets are for numbers. Images are for looking at. That model works nearly all the time, which is exactly why it’s so hard to dislodge — and why explaining “a PDF can contain active content” tends to be met with polite scepticism.
A playable game inside a document does in ten seconds what an article struggles to do in a thousand words. It replaces an abstract claim with something you can click.
And the deeper point holds well beyond PDFs. Formats accumulate features over decades. Each addition made sense to someone solving a real problem — form validation is genuinely useful, and so is a document that can check its own arithmetic. The result is that the ordinary things we exchange every day are considerably more capable than their names suggest. Capability, once it exists in a specification, is available to everyone who reads the specification.
Where this leaves the everyday stuff
Nothing here is an argument against PDF. It remains the best format there is for sending a document that will look the same everywhere, on any machine, years from now. That’s a genuinely hard problem, and PDF solved it. The features that make doompdf possible are the same features that make a fillable tax form possible.
It’s an argument for knowing what you’re handling. The same versatility that lets a document carry a game also lets it carry scripts, attachments, hidden layers and metadata you never intended to send. Those are worth understanding, and none of them are reasons for alarm.
It’s also part of why PDF Manipulator runs entirely on your own computer. When you’re merging, splitting or converting files, the fewer parties involved the better — not because online services are sinister, but because a document that never left your machine is a much simpler thing to reason about than one that has been on somebody else’s server.
Work with your PDFs entirely offline — PDF Manipulator is free →


Sources
- ading2210, doompdf on GitHub — source code and technical write-up; Emscripten 1.39.20, 320×200 six-colour output, ~80 ms per frame, GPL v2
- ading2210, linuxpdf on GitHub — Linux on a TinyEMU RISC-V emulator inside a PDF, 30–60 second boot
- Playable version (Chromium-based browsers)
- Eric Lawrence, Browser Security Bugs that Aren’t: JavaScript in PDF — what browser PDF engines do and do not allow scripts to reach
- Adobe, Restrict JavaScript API access in Acrobat
- DoomWiki, Licences — source release 23 December 1997, GPL relicence 3 October 1999
- The Register, It’s Doom … running in a PDF file
- Ars Technica, This PDF contains a playable copy of Doom


