# Модель загроз AfterPack: захищена поверхня

Матеріал для безпекового рев'ю AfterPack: актив, який він захищає, що відновлює кожен клас зловмисників, як зберігається секрет, де закінчується поточний обсяг і які засоби контролю працюють поруч із ним.

Source: https://www.afterpack.dev/uk/docs/threat-model

AfterPack захищає один актив: **JavaScript-артефакт, який видає ваша збірка**. Він переписує цей артефакт так, щоб читання, зняття відбитка чи патчинг коштували зловмисникові справжньої роботи, а інструменти, зроблені під одну збірку, ламалися на наступній.

Ця сторінка написана для безпекового рев'ю. Вона описує захищену поверхню, що відновлює кожен клас зловмисників, точку, де контроль на етапі збірки перестає діяти, і засоби контролю, які покривають решту.

## Захищена поверхня

| Що захищено | Атака, яку це знімає з порядку денного | Властивість, що робить роботу |
|---|---|---|
| Читабельність бандла, який ви випускаєте | Вставити бандл в інструмент чи модель і отримати назад ваш вихідний код | Ідентифікатори перейменовано, рядки закодовано, потік керування сплощено, а тотожності злито, тож прочитати бандл назад до вашого вихідного коду коштує реальної роботи, яку доводиться повторювати з кожною збіркою |
| *Структура* вашого бандла | Один раз написати деобфускатор, сигнатуру чи скрипт-патч і повторно використовувати їх між релізами | Новий [`seed`](https://www.afterpack.dev/uk/docs/config#seed) для кожної збірки, тож інструменти, написані під шаблони однієї збірки, ламаються на наступній |
| Атрибуція вашої реалізації | Довести, що випущений бандл — це ваш код, ваша бібліотека чи ваш алгоритм | Статичний читач мусить повторювати роботу з відновлення класу «Перейменовано й закодовано» на кожній збірці, перш ніж зможе зіставити результат із вашим; класи, що знищують походження й прибрали б цей збіг повністю, сьогодні не створюються |
| Рядковий матеріал, з яким ви порівнюєте значення | Пошук у бандлі токена чи рядка перевірки через grep | [Мінімальне кодування рядків](https://www.afterpack.dev/uk/docs/config#strings-encode), а для перевірки на рівність [нематеріалізація](#protecting-a-secret). На `light` числа лишаються читабельними |
| Цілісність артефакту під час використання | Пропатчити одну перевірку і випустити пропатчену збірку | Новий [`seed`](https://www.afterpack.dev/uk/docs/config#seed) переносить місце патча в кожному релізі. [Самоперевірка цілісності](#anti-tamper) виявляє зміни лише у власній таблиці перевірок |

Усе нижче уточнює ці п'ять рядків: кого треба перемогти, як далеко сягає кожна властивість і чого вона не досягає.

## Класи зловмисників

Дві осі, а не одна шкала. **[Статичний зловмисник](https://www.afterpack.dev/uk/docs/reversal-classes#static-attacker-defined)** читає байти: grep, інструменти для AST, прохід деобфускатора або передова модель, яка пояснює код, не виконуючи його. **Динамічний зловмисник** запускає артефакт: у пропатченому середовищі виконання, з перехопленими вбудованими функціями або на записаній трасі виконання, яку відтворюють офлайн. Трансформація може бути сильною проти читача і слабкою проти того, хто запускає код, а змішування цих двох — найпоширеніше перебільшення в цій категорії.

Шкала нижче впорядкована за можливостями зловмисника. Вартість відносна до інших рядків, а не абсолютна величина.

| Щабель | Зловмисник | Масштаб | Вартість для зловмисника | Результат |
|---|---|---|---|---|
| **A0** | Статичні шаблонні інструменти: grep, AST-матчери, детерміновані проходи деобфускації | одна збірка | Мізерна | Відновлює те, що лишилося відкритим текстом. Готові деобфускатори не додають нічого понад grep ([виміряні результати](#measured-results)). |
| **A1** | Модель наосліп: одне прочитання, без виконання, без інструментів | одна збірка | Мізерна | Розвернула більшу частину прочитаного: на трьох малих програмах повністю розвернула всі три на `light`, дві на `medium` і одну на `extreme`, а там, де не змогла відтворити програму, що запускається, однаково відновила більшість закладених секретів ([виміряні результати](#measured-results)). |
| **A2** | Агентна модель із виконанням, інструментами та бюджетом | одна збірка | Низька, на кожну збірку | Ця збірка не встоює: запуск коду відкриває значення, які він використовує. Інструменти, зроблені під форму цієї збірки, доводиться переробляти для наступної. |
| **A3** | Модель, навчена на великій вибірці власного результату AfterPack | увесь розподіл, а не одна збірка | Одноразова інвестиція, далі мізерна на кожну збірку | Не виміряно. Див. нижче. |
| **A4** | Інструментований динамічний аналіз: перехоплені вбудовані функції, записане виконання, знімки heap | одна збірка, дешево повторюється | Час аналітика, на кожну збірку | Падає для рядків: runtime-хук відновив 96 із 97 на кожному пресеті ([виміряні результати](#measured-results)). Див. [межу](#the-boundary). |
| **A5** | Привілейоване середовище виконання: пропатчений браузер, нативні хуки нижче рівня JavaScript | одна збірка | Високі витрати на підготовку, далі мізерні | Падає для всього, що виконується на клієнті. |

Щаблі накопичуються за можливостями, а не за ймовірністю. A0 покриває переважну більшість реальних атак на випущений JavaScript: хтось запускає безкоштовний інструмент або вставляє ваш бандл у вікно чату. A5 — рідкісний і дорогий фінал, з яким більшість продуктів ніколи не стикається.

**A0–A2 атакують одну збірку.** Новий [`seed`](https://www.afterpack.dev/uk/docs/config#seed) для кожної збірки, якщо ви його не зафіксували, змінює форму, тож розпізнавач чи патч, написаний під одну збірку, доводиться переписувати для наступної. Значень він не ховає: усе, що використовує код, може прочитати той, хто його запускає.

**A3 атакує весь розподіл результатів.** Модель, навчена на достатньо великій вибірці, вчиться бути інваріантною до варіативності між збірками, і ротація вашого сіду їй нічого не коштує. Що досі допомагає, так це прицільність: [Pro](https://www.afterpack.dev/uk/docs/pro#what-pro-buys) застосовує важчий пресет до [позначених вами ділянок](https://www.afterpack.dev/uk/docs/directives#what-you-can-set) і додає два типи трансформацій, які вмикаються явно: [`transforms.selfIntegrity.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled) і [`transforms.comparisonHardening.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled). Позначайте те, що справді важливо; див. [Найкращі практики](https://www.afterpack.dev/uk/docs/best-practices).

**A4 і A5 повністю виходять за межі статичного артефакту.** [Межа](#the-boundary) описує обидва.

### Виміряні результати

Що кожен зловмисник відновив із результату рушія 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, не робить відновлення неможливим, і ніщо на цій сторінці не слід читати як таке твердження.

[Стандартний пресет](https://www.afterpack.dev/uk/docs/presets#the-default-is-light) перейменовує ідентифікатори й кодує рядкові літерали. Починаючи з `medium`, AfterPack робить більше: потік керування сплощено, тотожності злито, а логіку переписано в еквівалентні форми, які стандартні інструменти не можуть згорнути назад. Зловмисник, який розвертає цей результат, може відновити робочу програму, але лише після реальної роботи з розпізнавання шаблонів, якої вимагають ці трансформації, а інструмент, написаний під форми однієї збірки, ламається на наступній. [Класи відновлення](https://www.afterpack.dev/uk/docs/reversal-classes) розбивають це на класи, з якими стикається статичний читач.

Сід [`seed`](https://www.afterpack.dev/uk/docs/config#seed) для кожної збірки за замовчуванням випадковий, тож дві збірки з того самого коду виходять структурно різними всюди. Інструменти, написані під шаблони збірки N, ламаються на збірці N+1, а значення, які хтось уже прочитав зі збірки N, лишаються прочитаними. Ця властивість окупається, лише якщо ви ротуєте збірки; [Найкращі практики](https://www.afterpack.dev/uk/docs/best-practices) і [Збірки та CI](https://www.afterpack.dev/uk/docs/builds) пояснюють, як вбудувати перезбірки в релізний конвеєр.

Ніщо з цього саме по собі не приховує секрет. Для цього потрібен інший механізм.

## Захист секрету

Секрет можна дістати з будь-якої програми, що поводиться так само, як ваша, зокрема з тієї, яку статичний читач відновлює із захищеної ділянки. Перебудова коду навколо секрету нічого для нього не робить.

Від того, хто читає байти, секрет захищає **нематеріалізація**, описана в розділі [Як уціліють секрети](https://www.afterpack.dev/uk/docs/concepts#how-secrets-survive). Параметр, що її забезпечує, [`transforms.comparisonHardening.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled), належить до Pro, вимкнений за замовчуванням і працює однаково на кожному рівні пресету.

Проти того, хто запускає ваш код, діє [межа](#the-boundary). Варіативність між збірками підвищує вартість повторного видобування секрету після кожної ротації. Універсальний хук у середовищі виконання, націлений на рушій JavaScript, коштує однаково в будь-якому разі, бо не залежить від структури AfterPack. [Як працює AfterPack](https://www.afterpack.dev/uk/docs/concepts#how-secrets-survive) ставить той самий механізм поруч із тим, що вже робить стандартний результат.

## Межа

Зловмисник, який запускає ваш код в інструментованому середовищі виконання, може дістатися до будь-якого значення, яке використовує сам код. Якщо запущеній програмі воно потрібне, наполегливий динамічний зловмисник може його побачити. AfterPack робить це значення дорогим для пошуку і дешевим для [ротації](https://www.afterpack.dev/uk/docs/config#seed). Він не робить його невідновлюваним.

> **Тримайте серверні повноваження подалі від клієнта**
>
> Ключам підпису, довготривалим обліковим даним і всьому, що зловмисник міг би повторно використати чи перепродати, місце на сервері, хоч би який обфускатор ви використовували.

Це обмеження не властиве лише AfterPack. [Кожен обфускатор етапу збірки](https://www.afterpack.dev/uk/docs/comparison) впирається в ту саму стіну, щойно зловмисник контролює середовище виконання. Що AfterPack зберігає за цією стіною, так це форму наступного релізу: інструменти, зроблені під одну збірку, доводиться переробляти для наступної.

## Захист від втручання

Самоперевірка цілісності, [`transforms.selfIntegrity.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled), додає перевірку над власною таблицею перевірок. Вона виявляє лише зміну цієї таблиці. Зміну будь-де ще у вашому коді, наприклад пропатчений `return true`, не виявлено.

Пасивного спостереження вона теж не виявляє: хук, що логує значення, читання heap чи нативна інструментація не змінюють нічого з того, що вона перевіряє. Це налаштування Pro, вимкнене за замовчуванням і глобальне; йому потрібен код рівня `medium` або вище, до якого можна прикріпитися, тож збірка на `light` містить його лише всередині ділянки, піднятої до такого рівня. [`preset=hard`](https://www.afterpack.dev/uk/docs/config#preset) залишає його вимкненим і натомість піднімає ділянку до [цільової складності](https://www.afterpack.dev/uk/docs/config#complexity) 12 з увімкненим [мінімальним кодуванням рядків](https://www.afterpack.dev/uk/docs/config#strings-encode).

## Що AfterPack не замінює

AfterPack — один засіб контролю в стеку, і безпекове рев'ю має бачити, де його межі. Кожен рядок нижче описує поточну зону дії засобу контролю на етапі збірки і засіб, що покриває решту. Зона дії змінюється з виходом нових можливостей продукту; [публічна дорожня карта](https://www.afterpack.dev/uk/roadmap) — єдине місце, де AfterPack повідомляє, що буде далі.

| Засіб контролю | Що AfterPack дає сьогодні | Що покриває решту |
| --- | --- | --- |
| **Захист на рівні запитів** (боти, скрапінг, зловживання) | Скрапер, якому потрібні структуровані дані з вашого бандла, мусить спочатку [його розвернути](https://www.afterpack.dev/uk/docs/reversal-classes). AfterPack діє на артефакт і не бачить запиту. | Сервіс challenge-response (reCAPTCHA, hCaptcha, Arkose) плюс обмеження частоти запитів на сервері за IP, сесією або API-ключем. |
| **Цілісність клієнта** (чити, автоматизація, пропатчені клієнти) | Автор читу чи автоматизації, який працює проти клієнта з [`preset=hard`](https://www.afterpack.dev/uk/docs/config#preset) і [поліморфізмом між збірками](https://www.afterpack.dev/uk/docs/config#seed), у кожному релізі наново проводить реальний аналіз, замість того щоб один раз пропатчити відоме зміщення. AfterPack підвищує цю вартість; арбітром він не є. | Валідація влучань, переходів стану та результатів на стороні сервера, де клієнт лише відображає рішення, які сервер уже ухвалив. |
| **Цілісність доставки** (проксі, CDN, розширення) | AfterPack захищає байти, які створює. Він не контролює шлях, яким вони проходять, а розширення, що використовує власний API браузера для блокування запитів, вирішує, що завантажувати, ще до виконання будь-якого JavaScript. | Subresource Integrity (`integrity="sha384-…"`), щоб браузер відмовлявся від бандла, який не збігається з хешем вашої збірки, плюс валідація на сервері всього, на що може вплинути посередник. |
| **Безпека застосунку** (баги, ін'єкції, зламана автентифікація) | Обфускація сповільнює пошук вади через читання вихідного коду. Вона не прибирає ваду, а той, хто дістається до неї через запущену програму, вашого вихідного коду взагалі не читає. | Виправте баг. [`npx afterpack@latest audit`](https://www.afterpack.dev/uk/docs/audit) сканує живий сайт на те, що він уже видає назовні. |
| **Рішення про довіру до клієнта** | [Поліморфізм між збірками](https://www.afterpack.dev/uk/docs/config#seed) перетворює одноразовий патч на регулярні витрати на повторний аналіз. | [Валідація на боці сервера](#not-a-substitute-for-server-authoritative-validation), нижче. |

### Не заміна валідації на боці сервера

Усі рядки вище мають спільну першопричину: перевірка ліцензії, платіжний гейт, правило прав доступу чи feature flag, які мають справді діяти, — це рішення, яке клієнт ухвалює сам про себе, і той, хто контролює цей клієнт, може його підробити. Це властивість виконання коду на клієнті, а не прогалина конкретного обфускатора, і жодна трансформація на етапі збірки цього не закриває.

Для всього, що має витримати ворожий клієнт, як-от ліцензування, платежі, права доступу чи результати матчів, ухвалюйте рішення на сервері, а клієнт хай лише його відображає. Внесок AfterPack [економічний](#what-obfuscation-protects), і він реальний: він підвищує регулярну вартість атаки на те, що справді виконується на клієнті.

## Далі

- [Що може відновити зловмисник](https://www.afterpack.dev/uk/docs/reversal-classes): класи статичного зловмисника детально, з діаграмою.
- [Як працює AfterPack](https://www.afterpack.dev/uk/docs/concepts): що стандартний результат уже робить із вашим бандлом.
- [Protection Map](https://www.afterpack.dev/uk/docs/protection-map): перевірте, який клас влучив у який рядок вашої власної збірки.
- [Найкращі практики](https://www.afterpack.dev/uk/docs/best-practices): що позначати, що ротувати і що тримати на сервері.
- [Конфіденційність і обробка даних](https://www.afterpack.dev/uk/docs/privacy): що залишає ваш комп'ютер, що зберігається і як довго.
- [Аудит](https://www.afterpack.dev/uk/docs/audit): скануйте живий URL на витоки, які обфускація не може скасувати.
- [Порівняння](https://www.afterpack.dev/uk/docs/comparison): чим AfterPack відрізняється від інструментів, які ви вже знаєте.
- [Тарифи](https://www.afterpack.dev/uk/docs/tiers): які щаблі вже покриває Free і що додає Pro.
