AfterPack захищає один актив: JavaScript-артефакт, який видає ваша збірка. Він переписує цей артефакт так, щоб читання, зняття відбитка чи патчинг коштували зловмисникові справжньої роботи, а інструменти, зроблені під одну збірку, ламалися на наступній.
Ця сторінка написана для безпекового рев'ю. Вона описує захищену поверхню, що відновлює кожен клас зловмисників, точку, де контроль на етапі збірки перестає діяти, і засоби контролю, які покривають решту.
Захищена поверхня
| Що захищено | Атака, яку це знімає з порядку денного | Властивість, що робить роботу |
|---|---|---|
| Читабельність бандла, який ви випускаєте | Вставити бандл в інструмент чи модель і отримати назад ваш вихідний код | Ідентифікатори перейменовано, рядки закодовано, потік керування сплощено, а тотожності злито, тож прочитати бандл назад до вашого вихідного коду коштує реальної роботи, яку доводиться повторювати з кожною збіркою |
| Структура вашого бандла | Один раз написати деобфускатор, сигнатуру чи скрипт-патч і повторно використовувати їх між релізами | Новий seed для кожної збірки, тож інструменти, написані під шаблони однієї збірки, ламаються на наступній |
| Атрибуція вашої реалізації | Довести, що випущений бандл — це ваш код, ваша бібліотека чи ваш алгоритм | Статичний читач мусить повторювати роботу з відновлення класу «Перейменовано й закодовано» на кожній збірці, перш ніж зможе зіставити результат із вашим; класи, що знищують походження й прибрали б цей збіг повністю, сьогодні не створюються |
| Рядковий матеріал, з яким ви порівнюєте значення | Пошук у бандлі токена чи рядка перевірки через grep | Мінімальне кодування рядків, а для перевірки на рівність нематеріалізація. На light числа лишаються читабельними |
| Цілісність артефакту під час використання | Пропатчити одну перевірку і випустити пропатчену збірку | Новий seed переносить місце патча в кожному релізі. Самоперевірка цілісності виявляє зміни лише у власній таблиці перевірок |
Усе нижче уточнює ці п'ять рядків: кого треба перемогти, як далеко сягає кожна властивість і чого вона не досягає.
Класи зловмисників
Дві осі, а не одна шкала. Статичний зловмисник читає байти: grep, інструменти для AST, прохід деобфускатора або передова модель, яка пояснює код, не виконуючи його. Динамічний зловмисник запускає артефакт: у пропатченому середовищі виконання, з перехопленими вбудованими функціями або на записаній трасі виконання, яку відтворюють офлайн. Трансформація може бути сильною проти читача і слабкою проти того, хто запускає код, а змішування цих двох — найпоширеніше перебільшення в цій категорії.
Шкала нижче впорядкована за можливостями зловмисника. Вартість відносна до інших рядків, а не абсолютна величина.
| Щабель | Зловмисник | Масштаб | Вартість для зловмисника | Результат |
|---|---|---|---|---|
| A0 | Статичні шаблонні інструменти: grep, AST-матчери, детерміновані проходи деобфускації | одна збірка | Мізерна | Відновлює те, що лишилося відкритим текстом. Готові деобфускатори не додають нічого понад grep (виміряні результати). |
| A1 | Модель наосліп: одне прочитання, без виконання, без інструментів | одна збірка | Мізерна | Розвернула більшу частину прочитаного: на трьох малих програмах повністю розвернула всі три на light, дві на medium і одну на extreme, а там, де не змогла відтворити програму, що запускається, однаково відновила більшість закладених секретів (виміряні результати). |
| A2 | Агентна модель із виконанням, інструментами та бюджетом | одна збірка | Низька, на кожну збірку | Ця збірка не встоює: запуск коду відкриває значення, які він використовує. Інструменти, зроблені під форму цієї збірки, доводиться переробляти для наступної. |
| A3 | Модель, навчена на великій вибірці власного результату AfterPack | увесь розподіл, а не одна збірка | Одноразова інвестиція, далі мізерна на кожну збірку | Не виміряно. Див. нижче. |
| A4 | Інструментований динамічний аналіз: перехоплені вбудовані функції, записане виконання, знімки heap | одна збірка, дешево повторюється | Час аналітика, на кожну збірку | Падає для рядків: runtime-хук відновив 96 із 97 на кожному пресеті (виміряні результати). Див. межу. |
| A5 | Привілейоване середовище виконання: пропатчений браузер, нативні хуки нижче рівня JavaScript | одна збірка | Високі витрати на підготовку, далі мізерні | Падає для всього, що виконується на клієнті. |
Щаблі накопичуються за можливостями, а не за ймовірністю. A0 покриває переважну більшість реальних атак на випущений JavaScript: хтось запускає безкоштовний інструмент або вставляє ваш бандл у вікно чату. A5 — рідкісний і дорогий фінал, з яким більшість продуктів ніколи не стикається.
A0–A2 атакують одну збірку. Новий seed для кожної збірки, якщо ви його не зафіксували, змінює форму, тож розпізнавач чи патч, написаний під одну збірку, доводиться переписувати для наступної. Значень він не ховає: усе, що використовує код, може прочитати той, хто його запускає.
A3 атакує весь розподіл результатів. Модель, навчена на достатньо великій вибірці, вчиться бути інваріантною до варіативності між збірками, і ротація вашого сіду їй нічого не коштує. Що досі допомагає, так це прицільність: Pro застосовує важчий пресет до позначених вами ділянок і додає два типи трансформацій, які вмикаються явно: transforms.selfIntegrity.enabled і transforms.comparisonHardening.enabled. Позначайте те, що справді важливо; див. Найкращі практики.
A4 і A5 повністю виходять за межі статичного артефакту. Межа описує обидва.
Виміряні результати
Що кожен зловмисник відновив із результату рушія 0.2.2, виміряно в жовтні 2026 року на п'яти програмах із закладеними секретами та на реальних продакшн-бандлах. Рядок передової моделі — окремий замір у жовтні 2026 року на рушії 0.2.6.
| Зловмисник | light | medium | hard і extreme |
|---|---|---|---|
| Шаблонні інструменти: webcrack, restringer, synchrony, terser | Нічого понад grep | Нічого понад grep | Нічого понад grep |
| Grep 42 закладених чисел | 42 | 18 | 18 |
| Статичне обчислення результату | 92–100% рядків | 96–98% рядків після проходу очищення, що зберігає поведінку | 96–98% рядків після того самого проходу |
| Runtime-хук на 15 рядків на вбудованій функції | 96 із 97 рядків | 96 із 97 рядків | 96 із 97 рядків |
| Передова модель, наосліп, без інструментів і без виконання | Усі 3 програми повністю розвернуто | 2 із 3 повністю розвернуто; третя віддала 12 із 17 секретів без відтвореної програми, що запускається | Лише extreme: 1 із 3 повністю розвернуто (9 із 9 секретів); інші віддали 12 із 17 і 2 із 3 секретів без відтворених програм, що запускаються |
У рядку передової моделі Claude Opus 5.5 отримувала лише обфускований файл, а 5 файлів, від яких вона відмовилася, пішли до Claude Opus 4.8; «повністю розвернуто» означає, що відтворений код друкує ті самі тестові вектори, що й оригінал, і містить кожен закладений секрет. Застереження: малий корпус із трьох програм, одна спроба на програму й пресет, і зловмисник лише Claude.
Що захищає обфускація
AfterPack має на меті дві властивості. Перша — ціна: відновлення збірки має коштувати більше, ніж те, що вона захищає. Друга — перевага в ритмі релізів: ви оновлюєтеся швидше, ніж інструменти зловмисника узагальнюються на наступну збірку. Жоден обфускатор, зокрема AfterPack, не робить відновлення неможливим, і ніщо на цій сторінці не слід читати як таке твердження.
Стандартний пресет перейменовує ідентифікатори й кодує рядкові літерали. Починаючи з medium, AfterPack робить більше: потік керування сплощено, тотожності злито, а логіку переписано в еквівалентні форми, які стандартні інструменти не можуть згорнути назад. Зловмисник, який розвертає цей результат, може відновити робочу програму, але лише після реальної роботи з розпізнавання шаблонів, якої вимагають ці трансформації, а інструмент, написаний під форми однієї збірки, ламається на наступній. Класи відновлення розбивають це на класи, з якими стикається статичний читач.
Сід seed для кожної збірки за замовчуванням випадковий, тож дві збірки з того самого коду виходять структурно різними всюди. Інструменти, написані під шаблони збірки N, ламаються на збірці N+1, а значення, які хтось уже прочитав зі збірки N, лишаються прочитаними. Ця властивість окупається, лише якщо ви ротуєте збірки; Найкращі практики і Збірки та CI пояснюють, як вбудувати перезбірки в релізний конвеєр.
Ніщо з цього саме по собі не приховує секрет. Для цього потрібен інший механізм.
Захист секрету
Секрет можна дістати з будь-якої програми, що поводиться так само, як ваша, зокрема з тієї, яку статичний читач відновлює із захищеної ділянки. Перебудова коду навколо секрету нічого для нього не робить.
Від того, хто читає байти, секрет захищає нематеріалізація, описана в розділі Як уціліють секрети. Параметр, що її забезпечує, transforms.comparisonHardening.enabled, належить до Pro, вимкнений за замовчуванням і працює однаково на кожному рівні пресету.
Проти того, хто запускає ваш код, діє межа. Варіативність між збірками підвищує вартість повторного видобування секрету після кожної ротації. Універсальний хук у середовищі виконання, націлений на рушій JavaScript, коштує однаково в будь-якому разі, бо не залежить від структури AfterPack. Як працює AfterPack ставить той самий механізм поруч із тим, що вже робить стандартний результат.
Межа
Зловмисник, який запускає ваш код в інструментованому середовищі виконання, може дістатися до будь-якого значення, яке використовує сам код. Якщо запущеній програмі воно потрібне, наполегливий динамічний зловмисник може його побачити. AfterPack робить це значення дорогим для пошуку і дешевим для ротації. Він не робить його невідновлюваним.
Ключам підпису, довготривалим обліковим даним і всьому, що зловмисник міг би повторно використати чи перепродати, місце на сервері, хоч би який обфускатор ви використовували.
Це обмеження не властиве лише AfterPack. Кожен обфускатор етапу збірки впирається в ту саму стіну, щойно зловмисник контролює середовище виконання. Що AfterPack зберігає за цією стіною, так це форму наступного релізу: інструменти, зроблені під одну збірку, доводиться переробляти для наступної.
Захист від втручання
Самоперевірка цілісності, transforms.selfIntegrity.enabled, додає перевірку над власною таблицею перевірок. Вона виявляє лише зміну цієї таблиці. Зміну будь-де ще у вашому коді, наприклад пропатчений return true, не виявлено.
Пасивного спостереження вона теж не виявляє: хук, що логує значення, читання heap чи нативна інструментація не змінюють нічого з того, що вона перевіряє. Це налаштування Pro, вимкнене за замовчуванням і глобальне; йому потрібен код рівня medium або вище, до якого можна прикріпитися, тож збірка на light містить його лише всередині ділянки, піднятої до такого рівня. preset=hard залишає його вимкненим і натомість піднімає ділянку до цільової складності 12 з увімкненим мінімальним кодуванням рядків.
Що AfterPack не замінює
AfterPack — один засіб контролю в стеку, і безпекове рев'ю має бачити, де його межі. Кожен рядок нижче описує поточну зону дії засобу контролю на етапі збірки і засіб, що покриває решту. Зона дії змінюється з виходом нових можливостей продукту; публічна дорожня карта — єдине місце, де AfterPack повідомляє, що буде далі.
| Засіб контролю | Що AfterPack дає сьогодні | Що покриває решту |
|---|---|---|
| Захист на рівні запитів (боти, скрапінг, зловживання) | Скрапер, якому потрібні структуровані дані з вашого бандла, мусить спочатку його розвернути. AfterPack діє на артефакт і не бачить запиту. | Сервіс challenge-response (reCAPTCHA, hCaptcha, Arkose) плюс обмеження частоти запитів на сервері за IP, сесією або API-ключем. |
| Цілісність клієнта (чити, автоматизація, пропатчені клієнти) | Автор читу чи автоматизації, який працює проти клієнта з preset=hard і поліморфізмом між збірками, у кожному релізі наново проводить реальний аналіз, замість того щоб один раз пропатчити відоме зміщення. AfterPack підвищує цю вартість; арбітром він не є. | Валідація влучань, переходів стану та результатів на стороні сервера, де клієнт лише відображає рішення, які сервер уже ухвалив. |
| Цілісність доставки (проксі, CDN, розширення) | AfterPack захищає байти, які створює. Він не контролює шлях, яким вони проходять, а розширення, що використовує власний API браузера для блокування запитів, вирішує, що завантажувати, ще до виконання будь-якого JavaScript. | Subresource Integrity (integrity="sha384-…"), щоб браузер відмовлявся від бандла, який не збігається з хешем вашої збірки, плюс валідація на сервері всього, на що може вплинути посередник. |
| Безпека застосунку (баги, ін'єкції, зламана автентифікація) | Обфускація сповільнює пошук вади через читання вихідного коду. Вона не прибирає ваду, а той, хто дістається до неї через запущену програму, вашого вихідного коду взагалі не читає. | Виправте баг. npx afterpack@latest audit сканує живий сайт на те, що він уже видає назовні. |
| Рішення про довіру до клієнта | Поліморфізм між збірками перетворює одноразовий патч на регулярні витрати на повторний аналіз. | Валідація на боці сервера, нижче. |
Не заміна валідації на боці сервера
Усі рядки вище мають спільну першопричину: перевірка ліцензії, платіжний гейт, правило прав доступу чи feature flag, які мають справді діяти, — це рішення, яке клієнт ухвалює сам про себе, і той, хто контролює цей клієнт, може його підробити. Це властивість виконання коду на клієнті, а не прогалина конкретного обфускатора, і жодна трансформація на етапі збірки цього не закриває.
Для всього, що має витримати ворожий клієнт, як-от ліцензування, платежі, права доступу чи результати матчів, ухвалюйте рішення на сервері, а клієнт хай лише його відображає. Внесок AfterPack економічний, і він реальний: він підвищує регулярну вартість атаки на те, що справді виконується на клієнті.
Далі
- Що може відновити зловмисник: класи статичного зловмисника детально, з діаграмою.
- Як працює AfterPack: що стандартний результат уже робить із вашим бандлом.
- Protection Map: перевірте, який клас влучив у який рядок вашої власної збірки.
- Найкращі практики: що позначати, що ротувати і що тримати на сервері.
- Конфіденційність і обробка даних: що залишає ваш комп'ютер, що зберігається і як довго.
- Аудит: скануйте живий URL на витоки, які обфускація не може скасувати.
- Порівняння: чим AfterPack відрізняється від інструментів, які ви вже знаєте.
- Тарифи: які щаблі вже покриває Free і що додає Pro.