Аудит JavaScript живого сайту

Скануйте живий URL на публічні source map, читабельний код і витоки облікових даних та отримайте оцінку зі 100. Той самий сканер, що працює в публічному сканері безпеки, з вашого терміналу.

npx afterpack@latest audit <url> завантажує JavaScript, який віддає сайт, і показує, що читач може з нього витягти. Це той самий сканер, на якому працює публічний сканер безпеки: публічні source map, наскільки читабельний ваш власний код, витоки облікових даних, а також без оцінки сторонній код, синки динамічного коду та виявлений стек.

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

Окремий інструмент, не рушій обфускації

audit не запускає рушій обфускації. Він завантажує ресурси, які віддає сайт, і аналізує те, що вже відкрито. Жоден із прапорців збірки на нього не діє.

Запуск

$ npx afterpack@latest audit https://yoursite.com

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

Лише живі URL

Режиму локального каталогу немає. npx afterpack@latest audit ./dist не підтримується. Аргументом має бути URL. Натомість перевірте preview-розгортання.

Що перевіряється

ПеревіркаЩо знаходить
Публічні source mapФайл .map поруч із будь-яким із ваших найбільших скриптів, знайдений за заголовком, коментарем або прямим запитом, і чи містить він ваш оригінальний код. Map із кодом обмежує оцінку до 10, map лише з mappings — до 50. Публічна тека .git рахується так само, як map із кодом.
Читабельний кодДля кожного вашого скрипта — скільки читач отримує як звичайний код: англійські рядки, осмислені імена та доступ до властивостей, виміряні на токенах. Кожен файл отримує рівень «як є», «мініфіковано» або «обфусковано». 75 балів, зважених за байтами. Відповідь на це питання для кожного токена дає Protection Map.
Витоки облікових данихПриватні ключі, хмарні секрети, платіжні секрети, токени репозиторіїв і чатів, URL баз даних і bearer-токени, показані замаскованими разом із контекстом. 25 балів. Email-адреси, IP-адреси та публічні браузерні ключі наведено без оцінки.
Сторонній кодСторонні SDK, які віддає сайт, розпізнані за хостом, шляхом або ліцензійним банером. Наведено окремо й не враховано в оцінці.
Гігієнаeval(), конструктор Function, document.write і сирі HTML-синки, сторонні домени та виявлений стек. Наведено без оцінки.

Відкриті source map

Source map веде від опублікованого бандла назад до вашого оригінального, читабельного вихідного коду. Ніколи не публікуйте його в продакшн: зловмисник завантажить його і читатиме ваш код таким, яким ви його написали.

Аудит це виявляє. Сам AfterPack за замовчуванням не записує поруч файл .map у продакшн-збірці (див. sourceMap.enabled і sourceMap.emitUrl), але він не може завадити вашому бандлеру, якщо той уже його видав.

Як читати результати

CLI друкує кожну фазу, щойно вона завершується, показує знахідки рівнів critical і high одразу, як вони надходять, а наприкінці виводить підсумковий блок: оцінку зі 100, кількість скриптів, знахідки за рівнем серйозності та виявлений стек. Завершується він списком усіх критичних знахідок і посиланням на повний звіт у вебі.

Читайте згори донизу:

  1. Спершу source map. Публічна map віддає читачеві ваш код таким, яким ви його написали, хай що робить збірка. Приберіть усі .map із продакшну.
  2. Далі облікові дані. Замініть будь-які облікові дані, що витекли, а потім припиніть їх публікувати.
  3. Читабельний код наостанок. Якщо ваші власні файли отримують рівень «як є» або «мініфіковано», суттєвого захисту в них немає. Пропустіть збірку через AfterPack (Швидкий старт займає близько п'яти хвилин).

За замовчуванням вивід є текстом для людини. --diagnostics.format=json натомість виводить у stdout один JSON-документ зі знахідками, оцінкою та посиланням на звіт, а кожен рядок для людини переходить у stderr; --diagnostics.level=none додатково вимикає фази прогресу. Звітом, яким можна поділитися, завжди є вебпосилання, яким завершується запуск.

Не оцінено

Сканування не отримує оцінки, коли сторінка не має власного коду сайту або сканер не зміг його прочитати. Звіт показує Не оцінено замість числа й пояснює чому:

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

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

Коди виходу

КодКоли
0Сканування завершилося. Зокрема й тоді, коли воно знайшло критичні проблеми.
1Сканування не вдалося: недосяжний URL, помилка на боці сервера, денний ліміт запитів або потік, що обірвався до завершення.
64Неправильне використання: URL не вказано, вказано більше одного URL або URL некоректний.

Це власні коди аудиту. Коди виходу збірки, які використовує запуск обфускації, окремі.

Аудит не є воротами CI

Оскільки завершене сканування повертає 0 незалежно від того, що воно знайшло, npx afterpack@latest audit … && deploy не падає через знахідки. Прапорця порогу серйозності немає: якщо хочете блокувати на знахідках, читайте їх самі з --diagnostics.format=json. Використовуйте аудит як крок перевірки перед релізом, результати якого ви читаєте вручну. Збірку зупиняє саме запуск обфускації.

Сканування без автентифікації обмежено до 3 на IP за 24 години, а один сайт можна сканувати 10 разів на годину. Коли ліміт вичерпано, команда друкує, скільки чекати, і завершується з кодом 1. Повторне сканування того самого URL протягом 30 хвилин повертає наявний звіт і не зараховується до ліміту.

Бейдж AfterPack

Розмістіть бейдж у футері сайту чи README. Він показує Protected by AfterPack, доки останнє сканування вашого хоста знаходить вихід AfterPack у власному коді сайту, жодних публічних source map чи облікових даних, і оцінку A. Інакше він показує останню оцінку або not graded, доки жодне сканування вашого хоста не оцінило сайт. Хост, який ніколи не сканували, показує Scan with AfterPack. Бейдж веде на останній звіт і оновлюється протягом години після нового сканування.

AfterPack badge

Футер:

<a href="https://www.afterpack.dev/security-scanner/site/yoursite.com?ref=badge" rel="noopener" title="AfterPack security scan">
  <img src="https://www.afterpack.dev/badge/yoursite.com.svg?style=compact&theme=dark" alt="AfterPack badge" width="200" height="32" loading="lazy">
</a>

README:

[![AfterPack badge](https://www.afterpack.dev/badge/yoursite.com.svg)](https://www.afterpack.dev/security-scanner/site/yoursite.com?ref=badge)

Стилі: compact (200×32) і wide (236×48) для футерів, flat (20 px) для README. Теми: dark і light. Кожна сторінка результатів сканера безпеки має ці фрагменти для свого хоста.

Далі

  • Збірки та CI: як вбудувати обфускацію у ваш релізний конвеєр і закріпити сід для відтворюваного результату.
  • Найкращі практики: що позначати, що не чіпати, і правило щодо source map.
  • Сканер безпеки: ті самі перевірки у вашому браузері, без встановлення, з повним звітом, яким можна поділитися.
  • Protection Map: погляд на вашу власну збірку на рівні токенів, щойно ви почнете обфускувати.
  • Чого AfterPack не замінює: секрет, що витік, потрібно замінити; обфускація постфактум не допоможе.