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

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

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

Жодних шарів обфускації, які можна зняти

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

AfterPack нічого з цього не постачає. Немає шару, який можна зняти, і немає фіксованої структури, за якою можна зняти відбиток: кожна частина результату залежить від кожної іншої, а вся форма змінюється з кожною збіркою, тож інструмент, написаний під одну збірку, не переноситься на наступну. Порівнянню з цими інструментами присвячено окрему сторінку.

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

Передова модель не просто підсумовує мініфікований код: агенти на кшталт Claude Code тепер деобфускують результат традиційних обфускаторів. В одному публічному експерименті агент розібрав і javascript-obfuscator, і комерційний інструмент (JScrambler) до читабельної логіки приблизно за десять хвилин (запуск описано в нашому блозі).

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

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

AfterPack працює після вашого бандлера, на зібраному результаті, і ніколи не зачіпає ваш вихідний код, через плагін для фреймворку або CLI після збірки. Швидкий старт є п'ятихвилинною версією.

AfterPack in your build pipelineYour source.ts / .tsx / .jsBundlerNext / Vite / …AfterPackpost-build sealPolymorphic bundledifferent every releaseCDNship itrandom seed per release → a structurally different artifact every time

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

  • Кодує ваші рядкові літерали. За будь-якої додатної цільової складності мінімальне кодування рядків увімкнене, тож рядковий літерал переписується у вибраний сідом декодер під час виконання замість того, щоб лежати в артефакті текстом. Це увімкнено за замовчуванням, і це найбільша відмінність від мініфікованого коду. Прологи директив, операнди порівняння з typeof, імена властивостей, потрібні рантайму, та імена експортів залишаються читабельними, а кілька рядкових значень із вихідного коду можуть залишитися всередині сильно мініфікованих сторонніх бандлів; збірка повідомляє, скільки їх уціліло, а Protection Map перелічує їх.
  • Переписує вашу логіку в еквівалентні форми, що знищують інформацію: змішана булево-арифметична логіка, непрозорі предикати, байткодова VM для цілочислових виразів. Зловмисник може відновити працездатну програму, але не ваш оригінал; алгоритмічний вибір утрачено. transforms.<kind>.enabled вмикає та вимикає окремі сімейства.
  • Перебудовує потік керування та структуру: сплощення потоку керування, мертві гілки, поглиблення областей видимості, переплетення перехресних залежностей.
  • Змінює все на кожній збірці завдяки поліморфізму для кожної збірки (див. нижче).

Стандартний варіант без конфігурації — light: мінімальне кодування рядків і перейменовані ідентифікатори, без структурного роздування. Підвищення пресету до medium або вище додає описану вище структурну роботу; читабельність рядків уже на своєму мінімумі незалежно від пресету. Усе це працює на кожному тарифі, зокрема Free; межу між Free і Pro описано на сторінці Тарифи.

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

AfterPack виводить результат із сіда для кожної збірки, який за замовчуванням випадковий. Дві збірки одного й того самого вихідного коду виходять структурно різними: інші імена, інші кодування, інша форма всюди.

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

Тож немає фіксованої структури, за якою можна зняти відбиток, і деобфускатор, написаний під одну збірку, не переноситься на наступну. Зловмиснику залишається вручну відновлювати одну конкретну збірку, і ця робота не переноситься: наступний реліз знову є іншою програмою. Часті релізи щоразу повторюють цю ціну. Як зробити це звичкою, описано в розділі Збірки та релізи.

Для відтворюваного результату, заради влучань у кеш або аудиту, закріпіть сід за допомогою --seed=git у CLI або seed: "git" у плагіні. Обидва варіанти виводять його з вашого коміту. Див. Збірки та релізи.

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

Не кожна трансформація підвищує ціну відновлення однаково. AfterPack розподіляє свій захист за класами відновлення; знаючи, який із них покриває ділянку, ви знаєте, з чим піде зловмисник.

Це класи для статичного зловмисника: вони описують, з чим стикається той, хто читає байти, grep, інструменти для AST або LLM, яка пояснює код, не запускаючи його. Зловмисник, який запускає артефакт в інструментованому рантаймі, є окремим, сильнішим випадком; його розглянуто нижче в розділі Межі та на сторінці Модель загроз.

Збірка на medium або вище досягає обох доступних класів у всьому бандлі; збірка на light залишається в першому, «Перейменовано й закодовано». Protection Map розфарбовує кожен токен за його складністю й називає клас коду, який ви виділили.

Перевизначення для ділянок, preset=hard і preset=extreme, підвищують цільову складність ділянки і примусово вмикають для неї мінімальне кодування рядків, зосереджуючи ту саму роботу там, де ви цього просите.

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

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

Від статичного читача або LLM, що читає код наосліп, секрет приховує нематеріалізація: значення ніколи не з'являється в результаті. transforms.comparisonHardening.enabled забезпечує її для літерала, з яким порівнює ваш код, переписуючи порівняння в перевірку одностороннього дайджесту, тож постачається лише дайджест. preset=extreme на секретному літералі робить відновлення дорогим, але літерал усе ще присутній у результаті.

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

Межі

Перевірка ліцензії в ділянці /* @afterpack preset=hard */, яка часто виходить у релізах зі змінним сідом, не варта інженерних годин на злам до виходу наступного релізу. Для більшості продуктів це правильна планка.

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

Далі

  • Класи відновлення: таблиця трьох класів докладно, для кожної трансформації.
  • Модель загроз: драбина супротивників від A0 до A5 і вісь «статичний проти динамічного».
  • Protection Map: перегляд по токенах, що доводить, який клас покрив який рядок.
  • Найкращі практики: що позначати, що не чіпати і як ротувати збірки.
  • Тарифи: повна межа між Free / Pro / Team / Enterprise.
  • Швидкий старт: встановіть плагін і випускайте захищений результат за кілька хвилин.
  • Фреймворки: плагін для вашого стека або шлях через CLI, коли плагіна немає.
  • Конфігурація: кожен згаданий вище ключ і через який інтерфейс його можна задати.
  • Пресети: драбина minify/light/medium/hard/extreme.
  • Директиви: граматика маркерів, що стоїть за preset=hard і skip.