# Як працює JavaScript-обфускатор AfterPack

Що стандартний результат (Free) робить із вашим кодом, як він протидіє відновленню і що зловмисник може насправді відновити.

Source: https://www.afterpack.dev/uk/docs/concepts

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

## Чому фіксовані шари обфускації не працюють

Більшість обфускаторів постачають дві речі, якими може скористатися зловмисник: стос шарів, застосованих один за одним, і заздалегідь заготовлені структури, які інструмент упізнає з першого погляду (масив рядків, навіть зашифрований, власний інтерпретатор VM, упізнаваний завантажувач декодера). Рецепт відновлення механічний: визначити шар або структуру за сигнатурою, зняти її, повторювати, доки не проявиться оригінал. `webcrack` і `restringer` роблять саме це, за мікросекунди.

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

*(animated fixed-pipeline vs per-build-shape comparison — see the web page)*

## AI-агенти змінили загрозу

Передова модель не просто підсумовує мініфікований код: агенти на кшталт Claude Code тепер деобфускують результат традиційних обфускаторів. В одному публічному експерименті агент розібрав і `javascript-obfuscator`, і комерційний інструмент (JScrambler) до читабельної логіки приблизно за десять хвилин ([запуск описано в нашому блозі](https://www.afterpack.dev/uk/blog/ai-deobfuscates-javascript)).

Перейменування, масив рядків і кілька шарів більше не дають захисту: це саме ті шаблони, з якими ці інструменти й моделі справляються найкраще. [Модель загроз](https://www.afterpack.dev/uk/docs/threat-model) показує, який супротивник долає яку техніку. Проти шаблонних інструментів досі працює нова форма в кожній збірці: розпізнавач, написаний під одну збірку, доводиться переписувати для наступної.

## Що вже робить стандартна обфускація

AfterPack працює після вашого бандлера, на зібраному результаті, і ніколи не зачіпає ваш вихідний код, через [плагін для фреймворку](https://www.afterpack.dev/uk/docs/frameworks) або [CLI після збірки](https://www.afterpack.dev/uk/docs/cli#what-a-run-does). [Швидкий старт](https://www.afterpack.dev/uk/docs/quickstart) є п'ятихвилинною версією.

*(build flow diagram — see the web page)*

Free застосовує все це:

- **Кодує ваші рядкові літерали.** За будь-якої додатної [цільової складності](https://www.afterpack.dev/uk/docs/config#complexity) [мінімальне кодування рядків](https://www.afterpack.dev/uk/docs/config#strings-encode) увімкнене, тож рядковий літерал переписується у вибраний [сідом](https://www.afterpack.dev/uk/docs/config#seed) декодер під час виконання замість того, щоб лежати в артефакті текстом. Це увімкнено за замовчуванням, і це найбільша відмінність від мініфікованого коду. Прологи директив, операнди порівняння з `typeof`, імена властивостей, потрібні рантайму, та імена експортів залишаються читабельними, а кілька рядкових значень із вихідного коду можуть залишитися всередині сильно мініфікованих сторонніх бандлів; збірка повідомляє, скільки їх уціліло, а [Protection Map](https://www.afterpack.dev/uk/docs/protection-map) перелічує їх.
- **Переписує вашу логіку в [еквівалентні](https://www.afterpack.dev/uk/docs/semantic-contract) форми, які стандартні інструменти не можуть згорнути назад**: змішана булево-арифметична логіка, непрозорі предикати, байткодова VM для цілочислових виразів. Статичний читач усе ще може дійти назад до вашого оригіналу ціною реальних зусиль, а інструмент, написаний під форми однієї збірки, ламається на наступній. [`transforms.<kind>.enabled`](https://www.afterpack.dev/uk/docs/config#transforms-kind-enabled) вмикає та вимикає окремі сімейства.
- **Перебудовує потік керування та структуру**: сплощення потоку керування, мертві гілки, поглиблення областей видимості, переплетення перехресних залежностей.
- **Змінює все на кожній збірці** завдяки [поліморфізму](#a-new-program-every-build) для кожної збірки (див. нижче).

Стандартний варіант без конфігурації — [`light`](https://www.afterpack.dev/uk/docs/config#preset): [мінімальне кодування рядків](https://www.afterpack.dev/uk/docs/config#strings-encode) і перейменовані ідентифікатори, без структурного [роздування](https://www.afterpack.dev/uk/docs/config#inflation-max). Підвищення [пресету](https://www.afterpack.dev/uk/docs/presets) до `medium` або вище додає описану вище структурну роботу; читабельність рядків уже на своєму мінімумі незалежно від пресету. Усе це працює на кожному тарифі, зокрема Free; межу між Free і Pro описано на сторінці [Тарифи](https://www.afterpack.dev/uk/docs/tiers).

## Нова програма на кожній збірці

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

Починаючи з `medium`, це більше, ніж косметичне перетасування. AfterPack змінює структуру самої програми, а не лише її текст: потік керування сплощується і перевпорядковується, значення обчислюються заново при кожному використанні замість того, щоб зберігатися, а частини бандла, які були незалежними, виходять переплетеними одна з одною. Постачається функціональний еквівалент того, що ви написали, інша програма, яка [поводиться так само](https://www.afterpack.dev/uk/docs/semantic-contract), а сід вирішує, який саме еквівалент ви отримаєте цього разу.

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

Для відтворюваного результату, заради влучань у кеш або аудиту, закріпіть сід за допомогою [`--seed=git`](https://www.afterpack.dev/uk/docs/config#seed) у [CLI](https://www.afterpack.dev/uk/docs/cli#flags) або [`seed: "git"`](https://www.afterpack.dev/uk/docs/config#seed) у плагіні. Обидва варіанти виводять його з вашого коміту. Див. [Збірки та релізи](https://www.afterpack.dev/uk/docs/builds).

## Що зловмисник може насправді відновити

Не кожна трансформація підвищує ціну відновлення однаково. AfterPack розподіляє свій захист за [класами відновлення](https://www.afterpack.dev/uk/docs/reversal-classes); знаючи, який із них покриває ділянку, ви знаєте, з чим піде зловмисник.

Це класи для статичного зловмисника: вони описують, з чим стикається той, хто читає байти, grep, інструменти для AST або LLM, яка пояснює код, не запускаючи його. Зловмисник, який запускає артефакт в інструментованому рантаймі, є окремим, сильнішим випадком; його розглянуто нижче в розділі [Межі](#scope) та на сторінці [Модель загроз](https://www.afterpack.dev/uk/docs/threat-model).

Збірка на будь-якому пресеті залишається в класі «Перейменовано й закодовано» в усьому бандлі; важчий пресет виконує більше цієї роботи, а не переходить до іншого класу. [Protection Map](https://www.afterpack.dev/uk/docs/protection-map) розфарбовує кожен токен за його складністю й називає клас коду, який ви виділили.

[Перевизначення для ділянок](https://www.afterpack.dev/uk/docs/directives#what-you-can-set), [`preset=hard`](https://www.afterpack.dev/uk/docs/config#preset) і [`preset=extreme`](https://www.afterpack.dev/uk/docs/config#preset), підвищують [цільову складність](https://www.afterpack.dev/uk/docs/config#complexity) ділянки і примусово вмикають для неї [мінімальне кодування рядків](https://www.afterpack.dev/uk/docs/config#strings-encode), зосереджуючи ту саму роботу там, де ви цього просите.

## Як уберегти секрети

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

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

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

## Межі

Перевірка ліцензії в ділянці [`/* @afterpack preset=hard */`](https://www.afterpack.dev/uk/docs/config#preset), яка часто виходить у релізах зі змінним [сідом](https://www.afterpack.dev/uk/docs/config#seed), не варта інженерних годин на злам до виходу наступного релізу. Для більшості продуктів це правильна планка.

Захист економічний. За необмеженого часу будь-який клієнтський код можна певною мірою відновити. Мета полягає в тому, щоб підняти ціну вище за цінність і змусити цю ціну повторюватися з кожним релізом. Коли актив вартує більше за будь-які зусилля з відновлення, тримайте його на сервері, де клієнт його ніколи не тримає. AfterPack посилює таку архітектуру; [він її не замінює](https://www.afterpack.dev/uk/docs/threat-model#what-afterpack-does-not-replace). [Посібник із найкращих практик](https://www.afterpack.dev/uk/docs/best-practices) пояснює, як витрачати захист там, де це важливо.

## Далі

- [Класи відновлення](https://www.afterpack.dev/uk/docs/reversal-classes): таблиця трьох класів докладно, для кожної трансформації.
- [Модель загроз](https://www.afterpack.dev/uk/docs/threat-model): драбина супротивників від A0 до A5 і вісь «статичний проти динамічного».
- [Protection Map](https://www.afterpack.dev/uk/docs/protection-map): перегляд по токенах, що доводить, який клас покрив який рядок.
- [Найкращі практики](https://www.afterpack.dev/uk/docs/best-practices): що позначати, що не чіпати і як ротувати збірки.
- [Тарифи](https://www.afterpack.dev/uk/docs/tiers): повна межа між Free / Pro / Team / Enterprise.
- [Швидкий старт](https://www.afterpack.dev/uk/docs/quickstart): встановіть плагін і випускайте захищений результат за кілька хвилин.
- [Фреймворки](https://www.afterpack.dev/uk/docs/frameworks): плагін для вашого стека або шлях через CLI, коли плагіна немає.
- [Конфігурація](https://www.afterpack.dev/uk/docs/config): кожен згаданий вище ключ і через який інтерфейс його можна задати.
- [Пресети](https://www.afterpack.dev/uk/docs/presets): драбина `minify`/`light`/`medium`/`hard`/`extreme`.
- [Директиви](https://www.afterpack.dev/uk/docs/directives): граматика маркерів, що стоїть за `preset=hard` і `skip`.
