W informatyce krąży żart, że DOOM prędzej czy później uruchomi się na wszystkim. Nie jako komplement pod adresem gry, tylko jako wyzwanie: strzelankę z 1993 roku zmuszono już do działania na bankomatach, drukarkach, testach ciążowych, kalkulatorach, pojedynczym klocku LEGO i na pasku dotykowym MacBooka.
W styczniu 2025 roku uczeń szkoły średniej dopisał do tej listy kolejną pozycję. Uruchomił DOOM wewnątrz pliku PDF.

W skrócie
Uczeń liceum skompilował DOOM do asm.js wersją Emscriptena z 2020 roku i uruchomił go w pliku PDF, używając jednego pola formularza na każdy wiersz ekranu: 320×200, sześć odcieni szarości, około 80 milisekund na klatkę. Nie użyto żadnej luki. Każda wykorzystana funkcja to udokumentowany element specyfikacji PDF, działający dokładnie tak, jak zaprojektowano. I to jest w tym najciekawsze — oraz powód, dla którego warto raz poświęcić dokumentom dziesięć minut uwagi.
To świetna robota i bardzo dobry żart. To także najczytelniejszy dowód na coś, co ta witryna powtarza od dawna, a w co ludzie mają pełne prawo nie wierzyć: PDF nie jest obrazkiem strony. Jest pojemnikiem, który potrafi wykonywać kod.
Jak to naprawdę działa
Projekt nazywa się doompdf, a stoi za nim programista podpisujący się ading2210. Mechanizm jest ciekawszy niż sam wyczyn i składa się z czterech części.
PDF obsługuje JavaScript. Nie jako dodatek czy wtyczkę — to część formatu, z własną biblioteką standardową, którą implementują także przeglądarki we wbudowanych silnikach PDF. Istnieje po to, żeby formularze mogły sprawdzać poprawność wpisywanych danych, a interaktywne dokumenty reagować na kliknięcia. Nikt nie dodał jej z myślą o grach.
Kod źródłowy DOOM-a jest publiczny — choć historia jest bardziej szczegółowa, niż sugeruje skrót myślowy. id Software opublikowało kod 23 grudnia 1997 roku, ale na licencji zezwalającej wyłącznie na zastosowania edukacyjne, i to kod linuksowego portu, nie oryginału na DOS — z powodu osobnej licencji biblioteki dźwiękowej DMX. Przejście na GPL nastąpiło prawie dwa lata później, 3 października 1999 roku. To ta druga data ma znaczenie: zamieniła DOOM-a z czegoś, co można przeczytać, w coś, co można legalnie zbudować od nowa. Dlatego gra wciąż pojawia się w nieoczekiwanych miejscach.
Oba światy połączył celowo przestarzały kompilator. ading2210 użył Emscriptena 1.39.20 — wersji z 2020 roku — ponieważ generuje ona asm.js, a nie WebAssembly. Współczesny Emscripten produkuje WebAssembly, a PDF nie ma środowiska uruchomieniowego dla WebAssembly. asm.js to ograniczony dialekt zwykłego JavaScriptu, więc działa wszędzie tam, gdzie działa JavaScript. Sięgnięcie po stare narzędzia nie było sentymentem, tylko jedyną drogą do środka.
Zostaje jeszcze wyświetlanie, czyli ta część, przy której ludzie wybuchają śmiechem. PDF nie ma płótna, nie ma bufora ramki, nie ma czego malować pikselami. Ma za to pola formularza. Obraz gry o rozdzielczości 320×200 jest więc renderowany znakami ASCII — jedno pole tekstowe na każdy wiersz ekranu, w sześciu odcieniach szarości — i odświeżany tak szybko, jak da się przepisać ten tekst, co daje mniej więcej 80 milisekund na klatkę. Sterowanie odbywa się tą samą drogą: przez pola i przyciski, które silnik PDF i tak potrafi obsłużyć. Grasz w DOOM-a dosłownie w formularzu do wypełnienia.
Działa wolno. Jest monochromatyczny. Jest w pełni grywalny, wydany na GPL v2 — tak jak kod, na którym się opiera — i można go samemu wypróbować w przeglądarce opartej na Chromium. Wersja źródłowa pozwala nawet podłożyć własny plik WAD.
Potem uruchomił w nim Linuksa
Kilka tygodni później ten sam programista opublikował linuxpdf: pełne jądro Linuksa startujące wewnątrz pliku PDF, dzięki skompilowaniu emulatora RISC-V TinyEMU tą samą sztuczką z asm.js. Jądro wstaje od 30 do 60 sekund — autor szacuje to na ponad sto razy wolniej niż na prawdziwym sprzęcie — a steruje się nim wirtualną klawiaturą zbudowaną z przycisków PDF.
DOOM w dokumencie to żart. Emulowany procesor uruchamiający system operacyjny w dokumencie to już argument. Gdzieś pomiędzy jednym a drugim przestaje chodzić o DOOM-a.
Ta część, która nie jest zabawna
Oto myśl, przy której warto się zatrzymać. Nic w doompdf nie jest exploitem. Nie znaleziono żadnej podatności, niczego nie złamano, nie użyto żadnej dziury w zabezpieczeniach. Każdy element, z którego korzysta ten projekt, to udokumentowana i zamierzona funkcja specyfikacji PDF, działająca dokładnie tak, jak przewidziano.

To znaczy, że zdolność pozwalająca PDF-owi uruchomić strzelankę z 1993 roku siedzi też w fakturze, którą otworzysz jutro. Nie czai się, nie jest ukryta — po prostu tam jest, nieużywana, bo większość dokumentów nie ma powodu z niej korzystać.
To jest uczciwa wersja tej historii i działa w obie strony. To samo rozumowanie, które mówi „dokument potrafi wykonać kod, więc uważaj”, musi też przyznać, jak wąski jest świat, w którym ten kod działa.
Co skrypt w PDF-ie może, a czego nie może
To miejsce, w którym większość tekstów o doompdf robi się mglista, więc warto być konkretnym. Odpowiedź zależy w całości od tego, w czym otworzyłeś plik — a dwa najczęstsze przypadki różnią się bardzo.
| Możliwość | Podgląd w przeglądarce (Chrome, Edge, Firefox) | Adobe Acrobat Reader |
|---|---|---|
| Wykonanie skryptu przy otwarciu | Tak | Tak, o ile nie wyłączono |
| Odczyt i zapis pól formularza | Tak | Tak |
| Dostęp do ciasteczek i pamięci przeglądarki | Nie | Nie dotyczy |
| Dostęp do strony HTML dookoła (DOM) | Nie | Nie dotyczy |
| Żądania sieciowe | Bardzo ograniczone | Szersze — tu mieszkały piksele śledzące i wycieki poświadczeń NTLM |
| Dostęp do plików lokalnych | Nie | Ograniczony, ale API jest znacznie większe |
| Uruchamianie programów i załączników | Nie | Za potwierdzeniem — historycznie tędy szły złośliwe dokumenty |
Tę tabelę trzeba czytać we właściwą stronę. W przeglądarce skryptowany PDF działa w małym, nudnym pudełku — bez ciasteczek, bez pamięci, bez dostępu do strony dookoła. Właśnie dlatego doompdf jest ciekawostką, a nie incydentem, i dlatego „DOOM działa w PDF-ie” nie jest powodem, żeby bać się PDF-ów.
Ciekawa jest kolumna z czytnikiem desktopowym. Ma on pełne API JavaScriptu opisane w specyfikacji, bo służy do obsługi prawdziwych dokumentów firmowych. To środowisko, w którym dokumentowi można kazać zameldować się gdzieś w sieci w chwili otwarcia, zachować się inaczej w zależności od czytnika albo poprosić o otwarcie czegoś, co niósł ze sobą.
Trzy rzeczy pozostają więc prawdą niezależnie od programu i to je warto zapamiętać.
- PDF może nieść instrukcje wykonywane w chwili otwarcia, zanim cokolwiek przeczytasz.
- PDF może zachować się inaczej w zależności od programu, który go otworzy — plik, który widzisz, nie musi być tym samym, co widzi twój współpracownik.
- PDF niesie więcej, niż pokazuje: załączniki, ukryte warstwy, historię zmian i metadane, których nie zamierzałeś wysłać.
Nic z tego nie czyni PDF-ów niebezpiecznymi w codziennym sensie. Otworzysz ich w tym miesiącu kilkadziesiąt i z każdym będzie dobrze. Znaczy to jednak, że model, który większość z nas nosi w głowie — „to tylko dokument” — jest błędny w sposób, który czasem ma znaczenie.
Ustawienie, o którym prawie nikt nie wie
Standardowa rada brzmi „wyłącz JavaScript w czytniku PDF” i jest dobra. Sama w sobie jest jednak niepełna — bo większość ludzi nie otwiera już PDF-ów w czytniku PDF. Otwiera je w karcie przeglądarki, a przeglądarka ma własny, osobny przełącznik.
Firefox dostarczany jest ze skryptami w PDF włączonymi. Ustawienie nazywa się pdfjs.enableScripting i znajduje się w about:config; do Firefoksa 87 miało wartość false, od Firefoksa 88 ma true. Ogólny przełącznik javascript.enabled go nie dotyka — podgląd PDF to osobny świat z osobnym ustawieniem.
Chrome i Edge w ogóle nie udostępniają osobnego przełącznika dla skryptów w PDF. Skrypt w pliku podlega uprawnieniu JavaScriptu dla witryny, z której plik pochodzi — można je wyłączyć dla pojedynczej strony w panelu przy pasku adresu albo globalnie pod chrome://settings/content/javascript, co jest narzędziem znacznie grubszym.
Adobe Acrobat Reader ma ten przełącznik, o którym wszyscy mówią: Preferencje → JavaScript → Włącz JavaScript programu Acrobat. To jego warto odznaczyć, bo Acrobat jest czytnikiem z dużym API, a prawie nikt świadomie nie używa skryptowanych PDF-ów w zwykłej pracy.
Praktyczny wniosek: wyłączenie tego w Acrobacie i zostawienie przeglądarki w spokoju to rozsądny, proporcjonalny wybór. Przekonanie, że wyłączyło się to wszędzie, gdy wyłączyło się tylko w Acrobacie — już nie.
Co z tą wiedzą zrobić
Praktyczna reakcja jest niewielka i warta tych dziesięciu minut.
Wyłącz JavaScript w czytniku desktopowym. W Acrobat Readerze to Preferencje → JavaScript. Usuwa całą kategorię ryzyka i nie kosztuje nic poza — trzeba przyznać — możliwością zagrania w DOOM-a w polu formularza.
Aktualizuj czytnik. Skrypty to jedna droga do środka. Druga to błędy w kodzie dekodującym czcionki i obrazy, a te naprawiają właśnie aktualizacje — i to one, historycznie, są częstszą drogą.
Traktuj niespodziewane dokumenty jako niespodziewane. Faktura od firmy, u której nigdy nic nie kupiłeś, zasługuje na chwilę zastanowienia, w jakimkolwiek formacie przyszła. To jest warte więcej niż jakiekolwiek ustawienie.
Zauważ, co łączy te trzy punkty: żaden nie wymaga rezygnacji z PDF-ów ani podejrzliwości wobec dokumentów w ogóle. To odpowiednik zamykania drzwi na klucz — tanie, nudne i rozsądne właśnie dlatego, że ryzyko jest małe, ale niezerowe.
Dlaczego ten projekt zasłużył na uwagę, którą dostał
Łatwo byłoby wrzucić doompdf do szuflady „ciekawostki z internetu” i przejść dalej. Twierdzę, że jest pożyteczniejszy, z powodu, który nie ma nic wspólnego z teatrem bezpieczeństwa.
Rozumienie formatów plików większość ludzi buduje wyłącznie na tym, do czego formaty służą. Dokumenty są do czytania. Arkusze do liczb. Obrazy do oglądania. Ten model działa niemal zawsze i właśnie dlatego tak trudno go ruszyć — a wyjaśnienie „PDF może zawierać aktywną treść” spotyka się zwykle z uprzejmym sceptycyzmem.
Grywalna gra w dokumencie robi w dziesięć sekund to, z czym artykuł mocuje się przez tysiąc słów. Zamienia abstrakcyjne twierdzenie w coś, w co można kliknąć.
Głębszy wniosek sięga daleko poza PDF-y. Formaty przez dekady obrastają w funkcje. Każdy dodatek miał sens dla kogoś, kto rozwiązywał realny problem — sprawdzanie poprawności formularza naprawdę się przydaje, podobnie jak dokument umiejący sprawdzić własne rachunki. Efekt jest taki, że zwyczajne rzeczy, którymi wymieniamy się codziennie, potrafią znacznie więcej, niż sugerują ich nazwy. A możliwość, która raz znalazła się w specyfikacji, jest dostępna dla każdego, kto tę specyfikację przeczyta.
Co z tego wynika dla codziennych plików
Nic z powyższego nie jest argumentem przeciwko PDF-owi. Pozostaje najlepszym formatem do wysłania dokumentu, który wszędzie wygląda tak samo, na dowolnej maszynie, także za wiele lat. To naprawdę trudny problem, a PDF go rozwiązał. Funkcje, dzięki którym doompdf jest możliwy, to te same funkcje, dzięki którym możliwy jest wypełnialny formularz podatkowy.
To argument za tym, żeby wiedzieć, z czym się pracuje. Ta sama wszechstronność, która pozwala dokumentowi nieść grę, pozwala mu też nieść skrypty, załączniki, ukryte warstwy i metadane, których nie zamierzałeś wysłać. Warto je rozumieć i żadna z nich nie jest powodem do niepokoju.
To także część powodu, dla którego PDF Manipulator działa w całości na twoim komputerze. Przy scalaniu, dzieleniu czy konwersji plików im mniej stron trzecich, tym lepiej — nie dlatego, że usługi online są podejrzane, ale dlatego, że dokument, który nigdy nie opuścił twojej maszyny, jest po prostu prostszy do ogarnięcia niż taki, który był na czyimś serwerze.
Pracuj na plikach PDF w pełni offline — PDF Manipulator jest darmowy →


Źródła
- ading2210, doompdf na GitHubie — kod źródłowy i opis techniczny; Emscripten 1.39.20, obraz 320×200 w sześciu odcieniach, ok. 80 ms na klatkę, GPL v2
- ading2210, linuxpdf na GitHubie — Linux na emulatorze RISC-V TinyEMU wewnątrz PDF-a, start jądra 30–60 sekund
- Wersja grywalna (przeglądarki oparte na Chromium)
- Eric Lawrence, Browser Security Bugs that Aren’t: JavaScript in PDF — co silniki PDF w przeglądarkach pozwalają skryptom osiągnąć, a czego nie
- Adobe, Restrict JavaScript API access in Acrobat
- DoomWiki, Licences — publikacja kodu 23 grudnia 1997, zmiana licencji na GPL 3 października 1999
- The Register, It’s Doom … running in a PDF file
- Ars Technica, This PDF contains a playable copy of Doom


