Юзерскрипт, патч від спільноти чи розширення змінює ваш застосунок, знаходячи текст у JavaScript, який ви постачаєте, і переписуючи його. Змінюйте те, що можна знайти, у кожному релізі, і патч перестане застосовуватися.
За що чіпляється патч
Авторові патча потрібен стабільний якір: ім'я функції, рядковий літерал, впізнавана форма, яку можна знову знайти в наступному завантаженому файлі. Мініфікація залишає всі три на місці. У мініфікованому бандлі все ще є імена функцій, скорочені, але однакові від збірки до збірки, ті самі рядкові літерали й та сама загальна структура, тож патч, написаний під один реліз, і далі спрацьовує на наступному.
Саме тому хороший патч живе місяцями. Автор тестує його на вашій поточній збірці, роздає своїм користувачам, і він працює в кожному релізі, який не зачіпає його якорів.
Структурні зміни прибирають форму, яку шукає патч
Одне лише перейменування просто перемістило б якір. Починаючи з medium, AfterPack переписує саму програму: потік керування сплощується й перевпорядковується, значення обчислюються заново при кожному використанні замість зберігання, а код, який був незалежним, виходить переплетеним. Постачається функціональний еквівалент того, що ви написали: інша програма, яка поводиться так само і яку обирає seed цієї збірки.
Тож патч, який раніше вставляв рядок у checkAccess, мусить спершу знайти код, що робить те, що робила checkAccess. Це вже не функція з таким ім'ям і не функція з такою формою. Механізм описано в розділі Як працює AfterPack.
Рядки, які шукає автор патча, зникають
strings.encode увімкнено на будь-якому додатному цільовому значенні complexity, тож рядкові літерали вашого JavaScript не є текстом в артефакті. Назва функції застосунку, тип повідомлення, шлях API, рядок прав доступу, текст, який показується, коли доступ закрито: grep опублікованого файлу не знаходить жодного з них, як і пошук із заміною, написаний під будь-який із них.
Ці літерали є найдешевшим якорем для патча, бо переживають мініфікацію без змін і читаються як документація до коду навколо них. Кодування — це частина збірки, яка їх прибирає.
Кожен реліз знову переміщує якорі
seed новий у кожній збірці, якщо ви його не закріпили, тож імена, кодування та форма відрізняються від вашого попереднього релізу. Тоді патч стає постійною статтею витрат для того, хто його підтримує: роботу доводиться повторювати для кожної збірки, яку ви випускаєте, а скрипт, уже розданий користувачам, перестає працювати в момент, коли ви розгортаєте нову версію.
Посильте захист там, де працює автор патча
medium підвищує захист у всій збірці:
{
"preset": "medium"
}Для коду, на який патч справді націлений, наприклад перевірки прав доступу, підніміться до hard:
$ npx afterpack@latest dist/ --preset=hardЗалишайте в продакшні випадковий сід. Саме сталий сід дає одному патчу спрацьовувати реліз за релізом; Стратегія сіду описує випадки, коли його безпечно закріпити. Якщо ви випускаєте релізи рідко, перезбирайте за розкладом, щоб форма все одно змінювалася; див. Ротація за розкладом.
Переконайтеся, що якорів немає
Пошукайте в артефакті, який збираєтеся розгорнути, імена й рядки, на які націлився б патч. Нічого не має знайтися.
Відкрийте Protection Map, яка записується, коли увімкнено protectionMap.enabled, і переконайтеся, що код, за яким полюватиме патч, покрито з очікуваною складністю. Потім запустіть verify як останній крок перед розгортанням: збірка записує у свій результат квитанцію захисту, а verify заново хешує кожен файл, названий у квитанції, і завершується помилкою, якщо якийсь із них більше не збігається.
Чого це не зупиняє
Патчинг триває. Той, хто прочитає нову збірку, може написати під неї новий патч, і ніщо в збірці не заважає розширенню змінювати вашу сторінку в браузері, який контролює його власник.
Юзерскрипт, що чіпляється за DOM, а не за ваш JavaScript, тобто за CSS-класи, структуру елементів чи видимий текст, не залежить від того, що AfterPack робить із бандлом. Змінюється кожен патч, якому потрібно знайти код: він коштує авторові роботи заново в кожному релізі, а його користувачі працюють зі зламаним скриптом, доки не отримають оновлення.
Далі
- Збірки та CI: перезбирання за розкладом і випадковий сід у продакшні.
- Найкращі практики: повна стратегія сіду, зокрема коли його безпечно закріпити.
- Захист перевірки пейволу: та сама механіка, застосована до перевірки прав доступу.