В программировании ходит давняя шутка: DOOM рано или поздно запустят на чём угодно. Не как похвалу игре, а как вызов. Шутер 1993 года уже заставляли работать на банкоматах, принтерах, тестах на беременность, калькуляторах, на одном-единственном кубике LEGO и на сенсорной панели MacBook.
В январе 2025 года старшеклассник добавил в этот список ещё один пункт. Он запустил DOOM внутри PDF-файла.

Коротко
Старшеклассник скомпилировал DOOM в asm.js версией Emscripten 2020 года и запустил его внутри PDF, используя по одному полю формы на каждую строку экрана: 320×200, шесть оттенков серого, около 80 миллисекунд на кадр. Никакой уязвимости здесь нет. Все использованные возможности — задокументированная часть спецификации PDF, работающая ровно так, как задумано. Именно это и интересно — и именно поэтому документам стоит один раз уделить десять минут.
Это прекрасная работа и очень хорошая шутка. А ещё это самое наглядное подтверждение того, что этот сайт повторяет постоянно и во что людям справедливо трудно поверить: PDF — не картинка страницы. Это контейнер, способный выполнять код.
Как это устроено на самом деле
Проект называется doompdf, его автор — разработчик под ником ading2210. Механизм интереснее самого трюка и состоит из четырёх частей.
PDF поддерживает JavaScript. Не как дополнение или плагин — это часть формата, со своей стандартной библиотекой, и браузеры реализуют её во встроенных движках PDF. Она существует для того, чтобы формы проверяли вводимые данные, а интерактивные документы отвечали на клики. Никто не добавлял её ради игр.
Исходный код DOOM открыт — хотя история точнее, чем следует из привычного сокращения. id Software опубликовала код 23 декабря 1997 года, но под лицензией, разрешавшей только образовательное использование, и это был код Linux-порта, а не оригинала для DOS: мешала отдельная лицензия звуковой библиотеки DMX. Переход на GPL состоялся почти два года спустя, 3 октября 1999 года. Важна именно вторая дата: она превратила DOOM из того, что можно прочитать, в то, что можно законно пересобрать. Поэтому игра и продолжает всплывать в самых неожиданных местах.
Оба мира соединил сознательно устаревший компилятор. ading2210 взял Emscripten 1.39.20 — версию 2020 года — потому что она собирает asm.js, а не WebAssembly. Современный Emscripten выдаёт WebAssembly, а в PDF нет среды исполнения WebAssembly. asm.js — ограниченный диалект обычного JavaScript, поэтому работает везде, где работает JavaScript. Обращение к старому инструментарию было не ностальгией, а единственным входом.
Остаётся вывод изображения — та часть, от которой люди смеются в голос. У PDF нет холста, нет буфера кадра, нечего закрашивать пикселями. Зато есть поля формы. Поэтому картинка 320×200 отрисовывается символами ASCII — по одному текстовому полю на каждую строку экрана, в шести оттенках серого — и обновляется так быстро, как этот текст удаётся переписать, то есть примерно за 80 миллисекунд на кадр. Управление идёт тем же путём: через поля и кнопки, которые движок PDF и так умеет обрабатывать. Вы буквально играете в DOOM внутри заполняемой формы.
Работает медленно. Монохромно. Полностью играбельно, распространяется под GPL v2 — как и код, на котором построено, — и это можно попробовать самому в браузере на движке Chromium. Сборка даже позволяет подставить собственный WAD-файл.
Потом он запустил в PDF Linux
Через несколько недель тот же разработчик выпустил linuxpdf: полноценное ядро Linux, загружающееся внутри PDF-файла, — эмулятор RISC-V TinyEMU собран тем же приёмом с asm.js. Ядро поднимается от 30 до 60 секунд — автор оценивает это как более чем в сто раз медленнее реального железа, — а управляют им виртуальной клавиатурой, собранной из кнопок PDF.
DOOM в документе — шутка. Эмулируемый процессор, загружающий операционную систему внутри документа, — уже аргумент. Где-то между этими двумя точками речь перестаёт идти о DOOM.
Часть, которая уже не смешная
Вот мысль, на которой стоит задержаться. Ничто в doompdf не является эксплойтом. Не найдено ни одной уязвимости, ничего не взломано, никакая дыра в безопасности не задействована. Каждая используемая деталь — задокументированная и намеренная функция спецификации PDF, работающая ровно так, как спроектировано.

Значит, возможность, позволяющая PDF-файлу выполнить шутер 1993 года, есть и в счёте, который вы откроете завтра. Она не притаилась и не спрятана — она просто есть, не используется, потому что большинству документов незачем ею пользоваться.
Это честная версия истории, и она режет в обе стороны. То же рассуждение, которое говорит «документ умеет выполнять код, будьте осторожны», обязано признать и то, насколько тесен мир этого кода.
Что скрипт внутри PDF может, а чего не может
Именно здесь большинство материалов про doompdf становится расплывчатым, поэтому будем конкретны. Ответ целиком зависит от того, чем вы открыли файл, — и два обычных случая различаются очень сильно.
| Возможность | Просмотр в браузере (Chrome, Edge, Firefox) | Adobe Acrobat Reader |
|---|---|---|
| Выполнить скрипт при открытии | Да | Да, если не отключено |
| Читать и записывать поля формы | Да | Да |
| Читать куки и хранилище браузера | Нет | Неприменимо |
| Добраться до окружающей HTML-страницы (DOM) | Нет | Неприменимо |
| Делать сетевые запросы | Очень ограниченно | Шире — здесь и жили следящие пиксели и утечки NTLM |
| Работать с локальными файлами | Нет | Ограниченно, но API заметно шире |
| Запускать внешние программы и вложения | Нет | С подтверждением — исторически путь вредоносных документов |
Читайте эту таблицу в правильную сторону. В браузере PDF со скриптами работает в маленькой скучной коробке: ни кук, ни хранилища, ни доступа к странице вокруг. Именно поэтому doompdf — курьёз, а не инцидент, и именно поэтому «DOOM работает в PDF» не повод бояться PDF.
Интересна колонка настольной читалки. У неё полный JavaScript-API из спецификации, потому что она предназначена для настоящих деловых документов. Это среда, в которой документу можно велеть отметиться в сети в момент открытия, вести себя по-разному в разных программах или предложить открыть то, что он принёс с собой.
Итак, три вещи остаются верными независимо от программы — их и стоит усвоить.
- PDF может нести инструкции, которые выполняются в момент открытия, до того как вы что-либо прочли.
- PDF может вести себя по-разному в зависимости от программы: файл, который видите вы, не обязательно тот же, что видит ваш коллега.
- PDF несёт больше, чем показывает: вложения, скрытые слои, историю правок и метаданные, которые вы не собирались отправлять.
Ничто из этого не делает PDF опасными в бытовом смысле. Вы откроете их десятки за месяц, и всё будет в порядке. Но это значит, что модель, которую держит в голове большинство из нас — «это же просто документ», — неверна так, что иногда это имеет значение.
Настройка, о которой почти никто не знает
Стандартный совет звучит «отключите JavaScript в программе для чтения PDF», и он хорош. Сам по себе он, однако, неполон: большинство людей давно не открывает PDF в отдельной читалке. Они открывают их во вкладке браузера, а у браузера свой, отдельный переключатель.
Firefox поставляется со включёнными скриптами в PDF. Настройка называется pdfjs.enableScripting в about:config; до Firefox 87 она была false, начиная с Firefox 88 — true. Общий переключатель javascript.enabled её не затрагивает: просмотрщик PDF — отдельный мир с отдельной настройкой.
Chrome и Edge вообще не дают отдельного переключателя для скриптов в PDF. Скрипт в PDF подчиняется разрешению JavaScript для сайта, с которого пришёл файл: его можно отключить для конкретного сайта в панели у адресной строки или глобально в chrome://settings/content/javascript — инструмент заметно более грубый.
Adobe Acrobat Reader обладает именно тем переключателем, который все имеют в виду: Установки → JavaScript → Включить JavaScript для Acrobat. Его и стоит снять, потому что Acrobat — читалка с большим API, а осознанно скриптованными PDF в обычной работе почти никто не пользуется.
Практический вывод: отключить это в Acrobat и не трогать браузер — разумный и соразмерный выбор. Считать, что отключил везде, отключив только в Acrobat, — нет.
Что со всем этим делать
Практический ответ невелик и стоит этих десяти минут.
Отключите JavaScript в настольной читалке. В Acrobat Reader это Установки → JavaScript. Это убирает целую категорию риска и не стоит ничего, кроме — надо признать — возможности поиграть в DOOM в поле формы.
Обновляйте читалку. Скрипты — один путь внутрь. Ошибки в коде, который разбирает шрифты и изображения, — другой, и именно их закрывают обновления; исторически этот путь встречается чаще.
Относитесь к неожиданным документам как к неожиданным. Счёт от компании, у которой вы ничего не покупали, заслуживает секунды раздумья, в каком бы формате он ни пришёл. Это ценнее любой настройки.
Обратите внимание, что общего у этих трёх пунктов: ни один не требует отказаться от PDF или подозревать документы вообще. Это эквивалент того, чтобы запирать входную дверь — дёшево, скучно и разумно именно потому, что риск мал, но не равен нулю.
Почему этот проект заслужил внимание
Было бы легко отправить doompdf в папку «интернет-курьёзы» и пойти дальше. Я считаю его полезнее, и причина не имеет ничего общего с театром безопасности.
Представление большинства людей о форматах файлов целиком построено на том, для чего форматы используются. Документы — чтобы читать. Таблицы — для чисел. Изображения — чтобы смотреть. Эта модель работает почти всегда, и именно поэтому её так трудно сдвинуть — и поэтому объяснение «PDF может содержать активное содержимое» встречают вежливым скепсисом.
Играбельная игра внутри документа делает за десять секунд то, с чем статья мучается тысячу слов. Она заменяет абстрактное утверждение тем, на что можно нажать.
И более глубокая мысль выходит далеко за пределы PDF. Форматы десятилетиями обрастают возможностями. Каждое дополнение имело смысл для того, кто решал настоящую задачу: проверка формы действительно полезна, как и документ, умеющий пересчитать собственные суммы. В итоге обыденные вещи, которыми мы обмениваемся ежедневно, умеют существенно больше, чем подсказывают их названия. А возможность, однажды попавшая в спецификацию, доступна каждому, кто эту спецификацию прочтёт.
Что из этого следует для повседневных файлов
Ничто из сказанного не является доводом против PDF. Он остаётся лучшим форматом для отправки документа, который везде выглядит одинаково — на любой машине и спустя годы. Это по-настоящему трудная задача, и PDF её решил. Те же возможности, что делают возможным doompdf, делают возможной и заполняемую налоговую форму.
Это довод за то, чтобы понимать, с чем имеешь дело. Та же универсальность, которая позволяет документу нести игру, позволяет ему нести скрипты, вложения, скрытые слои и метаданные, которые вы не собирались отправлять. В них стоит разобраться, и ни одна из них не повод для тревоги.
Это ещё и часть причины, по которой PDF Manipulator работает целиком на вашем компьютере. Когда вы объединяете, разделяете или конвертируете файлы, чем меньше участников, тем лучше — не потому, что онлайн-сервисы зловещи, а потому, что документ, который никогда не покидал вашу машину, куда проще осмыслить, чем тот, что побывал на чужом сервере.
Работайте с PDF полностью офлайн — PDF Manipulator бесплатен →


Источники
- ading2210, doompdf на GitHub — исходный код и техническое описание; Emscripten 1.39.20, вывод 320×200 в шести оттенках, ~80 мс на кадр, GPL v2
- ading2210, linuxpdf на GitHub — Linux на эмуляторе RISC-V TinyEMU внутри PDF, загрузка 30–60 секунд
- Играбельная версия (браузеры на движке Chromium)
- Eric Lawrence, Browser Security Bugs that Aren’t: JavaScript in PDF — что движки PDF в браузерах разрешают скриптам, а что нет
- Adobe, Restrict JavaScript API access in Acrobat
- DoomWiki, Licences — публикация кода 23 декабря 1997 года, переход на GPL 3 октября 1999 года
- The Register, It’s Doom … running in a PDF file
- Ars Technica, This PDF contains a playable copy of Doom

