Тази статия обяснява значението на разбирането как работят скриптовете за жизнения цикъл на npm като preinstall и postinstall, как биха могли (и са били) използвани злонамерено и предлага някои съвети за това какво можете да направите по въпроса като част на здравето на вашия npm проект.

Проблем

Ако използвате npm, популярния мениджър на пакети на JavaScript, вероятно сте чували за пакетната атака eslint-scope, при която контролът върху пакета, на който се разчита, е получен от злонамерен актьор, който публикува нова версия, съдържаща злонамерен код. Този злонамерен код беше изпълнен с помощта на скрипт за жизнения цикъл postinstall, което означава, че всеки потребител, който е инсталирал пакета, потенциално е имал своите данни за вход в npm регистъра, изпратени до отдалечен адрес от злонамерения скрипт. Официалният доклад за инцидента с npm може да бъде намерен тук, но важната подробност е, че несъзнателно потребителите, изпълняващи познатата команда npm install, нямаха представа, че този злонамерен код се изпълнява по време на стъпка postinstall. Тъй като тези скриптове се изпълняват по подразбиране, всички фонови задачи, които изпълняват, често са скрити от потребителя, който търси само обратна връзка дали инсталираното от него ново нещо е готово или не.

Пример:

// package.json file
"name: "express-example-package",
"scripts": {
  "postinstall": "node malicious.js"
}

Ако горният файл package.json беше примерен пакет в регистъра на npm, всеки потребител, който реши да npm install express-example-packageщеше да изпълни горния postinstall скрипт - съдържанието на този скрипт може да бъде всичко! Същото поведение е вярно за скриптовете preinstall , postinstall , preuninstall и postuninstall. Справката за npm за тези скриптове е достъпна тук.

Предотвратяване

В действителност предотвратяването на този проблем е много по-трудно от едно просто решение. Тези кукички за жизнения цикъл са важна характеристика - те могат да помогнат за настройване на пакети по сложни начини и да изпълнят важни задачи за почистване или подготовка, така че може да бъде ограничаващо просто да се откажете от изпълнението на тези кукички. Поради това препоръчителният подход за предотвратяване на този проблем винаги ще бъде да 1) внимателно преглеждате зависимостите и да използвате заключващ файл, за да предотвратите автоматичното инсталиране на нови пакети

2) Отказ от стартиране на скриптове при инсталиране

Когато инсталирате пакет, можете да изберете да се откажете от стартиране на скриптове, като използвате опцията ignore-scripts в npm или Yarn:

npm install --ignore-scripts

yarn add --ignore-scripts

Или, ако никога не искате да изпълнявате тези скриптове, когато инсталирате пакети, можете да промените вашата глобална конфигурация на npm:

npm config set ignore-scripts true

yarn config set ignore-scripts true

Забележка: тази настройка може също да се добави към .npmrc или .yarnrc файла на проекта.

3) Одит на текущото използване на скриптове на модули

Открих липса на налични инструменти, за да видя кои зависимости в текущото дърво на зависимости в момента изпълняват скриптове за жизнения цикъл, така че публикувах cli инструмент, за да прегледам тази информация. „Достъпно е на npm.“

За да използвате инструмента, можете да го инсталирате глобално npm install npm-viewscripts -g.

В директория на проект, стартирането на npm-viewscripts ще предостави списък на всички зависимости, инсталирани в момента, които имат, и ще продължи да изпълнява скрипт при инсталиране или деинсталиране.

Мислите ми

Този тип уязвимост не е грешка на npm, тъй като тези скриптове за жизнения цикъл са много полезна функция за управление на пакети, но рисковете трябва да бъдат разбрани от потребителите. Може да се твърди, че проблемът има по-широк обхват с npm поради големия размер на дървото на зависимостите на типично Node.js приложение и философията на изграждане, споделяне и потребление на много малки и отделни модули.

Мисля, че е важно общността и по-специално поддържащите популярни пакети да вземат предпазни мерки, за да предотвратят продължаването на тези атаки - най-добрата превенция срещу това е да се активира 2FA за всички npm акаунти с достъп за запис на пакети. Когато това е активирано, всички идентификационни данни за npm, които са откраднати по един или друг начин, имат по-малко вреда за потребителите на пакета, но това, разбира се, не предотвратява внезапното изкривяване на доверен поддържащ.

npm вършат страхотна работа, за да намалят риска от тези видове атаки, като намаляват typosquatting и предлагат безплатни инструменти за сигурност като npm audit.