Pull to refresh

Comments 120

UFO just landed and posted this here

Если бы в статье был сделан вывод, что нужно проверять любые зависимости в проектах на любом языке — это была бы сразу годная и хорошая статья. Проблема в том, что после её прочтения возникает ощущение, что проблема именно в npm. После прочтения статьи мне люди пишут (дословно): "Жопа с этими нпм пакетами, чел правду говорит же". А те, кто используют другие технологии, считают, что проблема к ним не относится.

UFO just landed and posted this here
Простите, а вы точно дочитали ту статью?
Моя цель (как оказалось) заключается в том, чтобы привлечь внимание к тому, что любой сайт, включающий в себя сторонний код, уязвим. Причём, его уязвимости практически нереально обнаружить. Надеюсь, этот мой рассказ дал пищу для ума тем, кого волнуют вопросы безопасности в сети.

Как я понял, npm был примером, который люди на эмоциях могли воспринять козлом отпущения. Но у автора была цель не дискредитировать npm, а призвать людей писать свои велосипеды внимательнее относиться к чужому коду.

А вы точно прочитали моё предисловие и послесловие? Я (и автор переведённой статьи) как раз говорим о том, что, вполне вероятно, что автор ставил себе благую цель, описанную в вашей цитате. Но сообщество восприняло статью (не только на хабре) слишком буквально.

Точно прочитал. А ещё я точно прочитал ваш предыдущий комментарий, в котором вы утверждаете, что никаких выводов автор первой статьи не делал. Как раз в итогах он не указал привязки к конкретному npm, он описал проблему в целом. Участники сообщества и пользователи npm могли воспринять это слишком близко к сердцу и, возможно, просто не смогли отделить одно от другого.
То, что в статье выше написано про аналогии с другими менеджерами пакетов и зависимостей, я с этим полностью согласен, как и автор предыдущей статьи, если судить по его выводам.
Тут косячит сам читатель. ¯_(ツ)_/¯

Пардон, я действительно некорректно сформулировал первый комментарий в этой ветке. Первое предложение оттуда нужно выкинуть.

В конце оригинальной статьи автор недвусмысленно советует критические к безопасности вещи (форма входа, запрос банковских данных) во-первых, детектировать и отдельно прорабатывать (в смысле на уровне подхода серьезнее к ним относиться), во-вторых писать руками и встраивать через <iframe> (в смысле приводит как один из вариантов практической реализации своего совета).
Чем не добротный вывод?

Проблема в том, что именно в nodejs-сообществе деревья зависимостей особенно развесистые. Вспомните историю с left-pad.
Т.е. проблема есть у всех, но масштаб разный.

Чувствую, ещё лет 10 будут этот лефтпад вспоминать.


В шарпе и джаве принято не ставить мелкие пакеты, а не глядя копипастить себе функции и классы с того же SO. Что по сути создаёт неявные зависимости и гораздо более опасно, чем зависимость от микромодулей.

Думаю, даже больше :-)
Копипаст функций менее опасен в плане зависимостей: скопированная функция не потянет за собой другую функцию из репы, которая потом обновится. Плюс их всё же читают, тогда как для пакета, вполне вероятно, ограничатся описанием.
Проблема тут другая: в скопированной функции с багом баг не будет исправлен никогда.


А вообще не вижу необходимости вступаться за npm: проблема очевидно не в нём, а в сложившихся практиках. И возможный результат панических статей — не отказ от ноды/нпм, а обострение NIH-синдрома у разработчиков: будут минимизировать зависимости. Ну и жёстко прибивать версии используемых пакетов (проводя перед этим code review всего дерева — что опять же обострит NIH-синдром)

Ждал, что будут описаны механизмы предотвращения попадания вредоносного кода в npm. Но суть тут лишь в том, что админы сами дураки, нужно проверять весь код, и вообще, посмотрите, вон в процессорах нашли уязвимость, типо всё уязвимо.

будут описаны механизмы предотвращения попадания вредоносного кода в npm

Предотвратить от попадания вредоносного кода в npm на самом деле нельзя. Он может быть в бинарниках С++ расширений, запрятан в исходниках, в подзависимостях, которые тащатся с гитхаба и так далее. Как раз речь о том, что ни один репозиторий пакетов не гарантирует вам безопасности — npm в том числе (хотя они пытаются, за что им плюс). И надо это понимать, а не валить на npm как на единственного козла отпущения. Это всего лишь репозиторий.


Если вас действительно интересует, как предотвратить попадание таких вещей в продакшн, то здесь всё довольно прозрачно, и в комментариях к оригинальной статье на хабре про это уже говорили — только вдумчивый код ревью может помочь (кстати, в самой статье про исправление ситуации тоже ничего не было). И, если вы обнаружили одну такую уязвимость и её отрепортили, то ребята из npm сразу поправят её везде. Помимо этого есть сканеры, например, snyc. Есть различные песочницы, докер и так далее. Всё есть — просто нужно этим пользоваться. И ответственность лежит на вас, и не надо её ни на кого перекладывать.

Без сомнения, для проворачивания такого трюка автор должен быть одарён просто потрясающими умениями социального инжиниринга
Ну да, конечно. Откуда же тогда берутся проекты, в которых +100500 ненужных зависимостей, которые не используются? Это столько много социальных инженеров?

Вы немножко спекулируете на теме.


В статье речь шла про автора, который якобы потратил заметное количество времени на реализацию фич или багфиксов для сотни проектов (прикиньте уже объём работы). А затем он якобы незаметно впихнул туда компонент, который покушается на святое святых, для чего вообще используются только проверенные пакеты — на логи. И якобы 20% радостно влили себе этот апдейт. Вот для этого реально нужны просто фантастические способности социального инжиниринга.


Насчёт лишних зависимостей — проблема есть, но она про другое. Обычно про необходимость совместимости со всеми версиями JS и затаскивание сотен стандартных либ вроде лодаша, бабеля, линтера и так далее. Но из их наличия абсолютно не следует, что авторы радостно добавят себе ноунейм библиотеку от непонятно кого с нулём зависимых в свой проект.

Вот для этого реально нужны просто фантастические способности социального инжиниринга.

Ни разу. Автор так в оригинале и говорит — "it is numbers game". Процент может быть и ниже, однако же динамика положительная. В больше репозиториев PR-нешься — больше заразишь. И если делать это достаточно долго, то в абсолютных числах количество инфицированных репозиториев будет столь же ужасающим. И никаких тебе маркетинговых талантов — просто систематический подход.

Да, а "сто старушек — уже рубль". Несопоставимые затраты труда и потенциальный профит.

Учитывая что куча людей пишут опенсорс запростотак, без профита вообще или ради строчки в резюме, перспектива продажи немаленькой базы данных кредиток вполне себе окупает затею. Ну… мне так кажется с моими представлениями об оплате труда.

1) Вам нужно будет завести кучу аккаунтов на нпм, чтобы вам всё не заблокировали разом.
2) Вам нужно будет прокачать каждый аккаунт, чтобы к нему было доверие
3) Вам нужно прокачать каждый пакет, который вы собираетесь внедрить. При этом зависимость должна быть уникальной и полезной — например, никто не примет ваш клон лодаша просто так.
4) Вам нужно написать разный вредоносный код, чтобы его не выпилили везде разом
5) Вам нужно сделать кучу полезных изменений в популярных пакетах, чтобы ваша зависимость прошла незаметно.


И со всем этим есть ещё риск попасться. Вот правда — слишком сложно. На таком уровне проще сениором работать — скорее всего и денег будет больше, и спать по ночам будете спокойно.

Эм… а при чем тут прокачка аккаунтов на нпм? Достаточно всего одного аккаунта с одной маленькой либой, которая делает разноцветное логирование. И одного пакета, что в статье и описывается.
Из ваших предположений истинен только п. 5, благо открытых issues в популярных пакетах полно.

Пакетов для разноцветного логирования уже огромное количество, и нет никаких оснований использовать именно этот. Кроме того — вы правда думаете, что ваше разноцветное логирование требуется какому-либо крупному пакету? Так что нужен оригинальный и полезный пакет.


А если делать один пакет и один аккаунт, то вас с большой скоростью отследят и выпилят. Так что истинны все изложенные мной пункты.

Есть такое явление, как «typo-squatting». Можно добавить зависимость на пакет, чьё имя похоже на «оригинальный и полезный пакет». Это вполне может прокатить. Вот реальный пример: habrahabr.ru/company/ruvds/blog/335144

Ага, и посылке хорошо показана судьба такого пакета. Не получил и 70 загрузок, был удалён и забанен вместе с остальными пакетами автора, на аналогичный код была осуществлена проверка. А сейчас ещё правила по пунктуации ужесточились и заработал спам фильтр.

Если не ошибаюсь, ситуации с такими названиями это ужесточение не покрывает: react-natiue, react-natiive, react-natjve и т.п.

Все равно лучше чем ничего. С именами с опечатками они борятся ручной модерацией и автоматической антиспам системой (описано вот здесь, "what we plan to do next").


Кроме того вы всегда можете помочь, есть официальный алгоритм, как добиться удаления спамного пакета.


Судя по тому, что все ваши примеры опечаток как пакеты не зарегистрированы, система работает хорошо.

Вы утверждаете, что всегда (100%) внедряются только прокачанные пакеты с прокачанных аккаунтов, исключительно с уникальным и полезным функционалом, и никогда не принимаются мелкие изменения?.. Хм.

Вы наерняка знаете, насколько эффективны фишинговые атаки? Да, 99% людей их смогут избежать, но 1 % который попадается, приносит ощутимый профит, настолько большой, что этим продолжают заниматься.

Иными словами.
Самое слабое звено — люди.
Если вы проведете сто мелких изменений слквых аккаунтов, то есть шанс, что одно примут. Ну а дальше масшатбируйте эти числа))

Нет, я утверждаю, что большой и востребованный пакет с нормальными разработчиками не примет мелкое изменение, которое включает в себя добавление никому не известного пакета.


Вероятность этого вполне сравнима с вероятностью идти по улице и найти 5000 рублей. Только для хождения по улице ещё и свой код писать не надо. А дальше — масштабируйте сколько угодно...

Не забывайте, что большой и востребованный пакет зачастую состоит из других мелких и менее востребованных пакетов, которые могут в итоге подцепить к себе эту зависимость, и в итоге такой пакет окажется и в большом… Достаточно внедриться в один из них, и вот — у вас уже многомиллионная аудитория, ничего не подозревающих людей, которые «доверяют большому востребованному пакету».

Вам нужно будет


1) Внедриться в маленький пакет. Как вы себе представляете, например, внедрение незаметной зависимости в leftpad?
2) Протолкнуть новый релиз этого пакета
3) Протолкнуть обновление вашего пакета в зависимости верхнего уровня. И так, возможно, несколько раз придётся идти наверх.
4) Чтобы в процессе этого никто вам не заметил.

Внедриться в leftpad? Помните ту историю, да? А теперь представьте себе, что обиженный разработчик не удалил свой пакет, а подсунул в него вредоносный код.
Или представьте себе, что кто-то взломал npm аккаунт автора leftpad. Плохие пароли встречаются у всех.

Представил. У всех зафиксированы зависимости и\или используется локи версий. Мало того, что зловред не поставится самопроизвольно на крупных серверах из-за локов, так его ещё и мгновенно отследят.

его ещё и мгновенно отследят

Судя по Heartbleed, «мгновенно» — это что-то около двух лет.

Абсолютно неуместная аналогия между сложным криптографическим модулем и простым npm модулем.

1) Внедриться в маленький пакет. Как вы себе представляете, например, внедрение незаметной зависимости в leftpad?

Во-первых никто не сказал, что зависимость будет невидимой. Она будет видима, но из-за обфускации кода её мало кто прочтёт.
А вариантов подцепиться к такому проекту как leftpad много: приходишь к автору и говоришь: «эй чувак, давай замутим еще rightpad, вдруг кому-то захочется использовать не только лево, но и право?»
Взлом некоей спящей учётки npm тоже отменять не стоит. (upd: упс, меня уже опредили).

4) Чтобы в процессе этого никто вам не заметил
А вы замечаете все изменения во всех 500 зависимостях используемых вами пакетов? Уверены ли вы на 100%, что там нету гадости, или вы, как и другие, полагаетесь, что «ну кто-то то точно это бы заметил»?
Ну вот, делаем right-pad2, но который «чудесно гибко интегрирован с left-pad». А еще не забывайте, что бывают опечатки (когда пакеты добавляются вручную), и можно сделать «rightpad», «rigthpad» итд итп)

Ещё раз — у пакета left-pad есть история и некая авторитетность. У вашего нового — нету. А проблема с опечатками точно так же справедлива для любого репозитория и вообще является частным случаем фишинга.

А если (внезапно) проект востребованный, а разрабочики на нем — так себе?..

Однако же вы делаете главную одну ошибку — относитесь к этому вопросу как приличный программист :-)
Поэтому и зациклились на крупных проектах.

Вы мыслите примерно так: «я сделал классный пакет, вложил кучу сил, и теперь хочу, чтобы он 99% попал в этот вот конкретный крупный проект. Это круто, это + в резюме, да и просто приятно.»
Нам всем это понятно, и всем хочется того же…

А нужно мыслить так: «Я сделал вредоносный пакет и мне все равно в какие пакеты он попадет, лишь бы побольше разных — через зависимости рано или поздно подтянется в большое число реальных, боевых проектов»
Это совершенно другая цель. Абсолютно все равно, заразите ли вы 100 сайтов через один большой пакет или через 50 мелких — вы все равно получите то, что хотите.

И, раз уж вы говорите «слишком сложно», то представьте количество даных, которые будет вам сливать ежедневно условный amazon, если вам удастся его заразить… Уверены, что прокачивание аккаунта и написание хорошего фикса того не стоят?)
И, раз уж вы говорите «слишком сложно», то представьте количество даных, которые будет вам сливать ежедневно условный amazon, если вам удастся его заразить… Уверены, что прокачивание аккаунта и написание хорошего фикса того не стоят?)

Уверен, что есть гораздо более простые способы собирать карточные данные, если вам уж так захотелось to the dark side.

Я, конечно, понимаю, что говорю с переводом, но всё же.
Я не увидел в оригинальной статье посыл, что «NPM — зло, давайте забьем разработчиков камнями». Она (на мой скромный взгляд, опять же) про то, что инфраструктура разработки — это тоже вектор атаки на продукт.
И тут хочется отметить несколько моментов:
Первый — автор «ответа» явно передергивает, когда сводит всё к «Автор уговорил разработчиков внедрить свой вредоносный код». Это немного искажает суть: Злоумышленнику достаточно убедить внедрить этот код кому-либо из разработчиков внутри вашего dependency-tree, что бы после обновления зависимостей вы получили у себя в продукте вредоносный код.

Второй — Да, опенсорс строится на доверии. Да, каждый из нас может делать его лучше. Да, подтягивая зависимости мы берем ответственность за последствия.
Это всё очевидно и правильно. Это не отменяет того факта, что в моем домашнем проекте, который я быстро накидал за пару выходных как proof of concept, объем кода в dependency tree в несколько раз больше, чем, собственно, в самом проекте.
Ну, просто потому, что Zen of Python и первая мантра разработчика: не пиши велосипед, используй готовое решение.
И да, я понятия не имею, что происходит под капотом у зависимостей дальше первого уровня дерева (т.е. кроме тех, которые я подтянул сам).
И далеко не у всех команд разработки есть ресурсы (будь-то сила, время или компетенция) изучить полностью древо зависимостей на предмет уязвимостей.
Потому что помимо интерпрайза есть инди-разработчики. Потому что помимо умудренных опытом дримтимов есть ребята, которые делают свой проект на коленке, а потом данные пользователей их мобильного приложения утекают черти куда.
Заслуживают ли такие разработчики пинков коллег, общественного порицания и ночных багфиксов потом? Возможно.
Но их пользователи определенно не заслуживают того, что бы их данные куда-то сливали из-за неосмотрительности разработчика.

Итог:
Сгустил ли автор оригинальной статьи краски про то, как просто всё это осуществить, что бы более драматично обрисовать масштабы уязвимости? Да, определенно.
Действительно ли этой проблеме нужно столько внимания, что бы на её тему поднимать панику и драматизировать? На мой взгляд тоже да.
Я, конечно, понимаю, что говорю с переводом, но всё же.

Ничего, я тоже эту статью перевёл, отвечая на перевод...


Я не увидел в оригинальной статье посыл, что «NPM — зло, давайте забьем разработчиков камнями».

И я тоже его не увидел. Но многие почему-то увидели. И не увидели, что проблема не только в npm. Ради этих людей автор написал эту статью, а я её перевёл. Рад, что вы к ним не относитесь.

Ну, просто потому, что Zen of Python и первая мантра разработчика: не пиши велосипед, используй готовое решение.

Я дико извиняюсь если не правильно понял, но нет в Zen of Python ни слова о велосипедах. Специально перечитал.

Нет языка кроме Питона и Гвидо Ван Россум пророк его.
Всё так, всё так. В целом, про велосипеды была отсылка именно к первой мантре разработчика.
Касательно Zen of Python, я бы сказал что в моей голове это тезис хорошо соотносится с Simplicity is better than Complicity, т.к. «не делать лишнюю работу и использовать готовые решения» — тоже часть упрощения твоего кода. Но в целом да, моё высказывание было не до конца корректным.
«не делать лишнюю работу и использовать готовые решения» — тоже часть упрощения твоего кода.

Упрощение кода — это не всегда верно, кто знает что автор решения нагородил. С другой стороны брать или не брать чужое тоже вопрос. Вопрос в том, что проще — изучить чужое или написать свое. А если не изучать, то встает тот самый вопрос доверия.
У npm есть две особенности:
1. Это реально самый большой и быстрорастущий репозиторий.
2. JavaScript в целом использует мантру переиспользования микромодулей, вплоть до упоротого случая с leftpad. На многих других языках разработчики обычно пишут такие функции, поэтому зависимостей получается меньше.

А так да, npm не виноват.
Это реально самый большой и быстрорастущий репозиторий.

Это вы сейчас минус привели?


JavaScript в целом использует мантру переиспользования микромодулей

Ага. И в микромодуль запихнуть левый код гораздо сложнее, чем в большой.

Это вы сейчас минус привели?

Это не минус, это особенности. Скажем, вокруг pypi почему-то таких скандалов особо нет. Разве что попытка подмены имен.


Ага. И в микромодуль запихнуть левый код гораздо сложнее, чем в большой.

Как часто вы ревьювите код микромодуля? Вы один раз его глянули и используете. А потом автор туда что-то добавил и код нужно опять ревьюить. Смысл в том, что если вы используете микромодули, то вам нужно ревьюить гораздо больше кода, чем при обычном подходе. Например, в случае проекта на java+spring или проекта python+django у вас обычно ряд классических зависимостей, которые не столь сильно нуждаются в ревью, потому что их разработчикам приходится доверять и 2-3 левых.


В случае javascript пакетов обычно значительно больше.

В случае javascript большая часть микромодулей точно так же стандартная. А ещё обновления стабильно работающих модулей обычно лочатся на всю глубину, чтобы на каждый чих не заниматься ревью.

Автор оригинальной статьи, кстати, вполне себе доступен в твиттере для общения.


Критикуется не сам npm. И упор в статье явно сделан не на том, что "ой смотрите, какой плохой npm!". В статье говорится о том, что современный стек JS-технологий таков, что для того, чтобы запустить средней руки приложение вам нужно ну никак не меньше 150 различных пакетов, некоторые из которых вполне себе leftpad-оподобны. И основная печаль в том, что всё JS-сообщество такой подход одобряет и поддерживает. "Да! Даёшь больше как можно мелких пакетов! Ееее, это unix way", говорят они. И вот тут я полностью согласен с автором, что происходящее напоминает какое-то безумие.


Дробление функциональности системы на подсистемы (частным случаем чего является политика распихивания всякого по разным пакетам) — своеобразная дисциплина специальной олимпиады для любого проектировщика. И любой более-менее опытный проектировщик знает как сложно найти баланс между god object (god package в нашем случае) и тысячью маленьких пакетиков, содержащих по одной функции. Так вот. Сообщество JS неосознанно сделало выбор в пользу второго варианта. И это же ужасно. Предыдущие 50 лет человечество старалось минимизировать зависимости при проектировании систем, а тут на тебе — приходит технология, в которой моду диктуют вчерашние бакалавры из около-IT ВУЗов, вдохновившиеся примерами микроядер (иного объяснения такому поведению я не нахожу) и, кладя с прибором на советы более опытных товарищей, начинают громко верещать про то, что маленькие пакеты — это unix way, круто и вообще. А кто так не делает — тот бездарь и вообще пшел вон из профессии.


Фишка в том, что ты можешь проверить все пакеты, от которых зависит твоя система если их, скажем, 10. Или их, скажем, 50. Или — б-г с ним — 100. Но когда их число только начинается от 150 — это решительно не представляется возможным. И это, к слову, только одна из возможных проблем мелкого дробления пакетов. Развивая тему, автор статьи в твиттере давеча написал примерно следующее:


Переведенный твит
$ npm install jest
> + jest@22.0.6
> added 510 packages in 38.618s

"Эй Jest, хошь прийти ко мне отдохнуть и поглядеть Netflix?"
"Ага, только я возьму с собой 509 друзей. Уверен, никто из них не попытается спереть твой тостер."


Таким образом, я делаю вывод, что автор этого ответного пафлета решительно не понимает предмета оригинальной статьи. Так то.

Забавно, что каждый видит в исходной статье нечто своё. Вот вы увидели критику стека JS технологий. Заставляет задуматься о преломлении восприятия даже казалось бы сугубо технических текстов.


Кстати насчёт jest — пользуясь аналогией автора — он-то конечно приводит 509 друзей. Но его самого ко мне приводит фейсбук. И хотя я не жду от фейсбука каких-то абсолютных гарантий, но он является хоть в какой-то мере доверенным поставщиком — точно так же, как любой другой крупный вендор произвольного софта. С такой же вероятностью "спереть мой тостер" может любой разработчик, к примеру, участвующий в проектах google chrome, linux или windows.

Не критику стека, внимание! Критику самого подхода сообщества. Стек-то нормальный но вот политика его развития диктуется, как по мне — так не самыми квалифицированными специалистами, мягко говоря. Но это мое ИМХО.
Фейсбук, если мне память не изменяет, как раз и прокололся на left pad-е. Хоть случай и не совсем релевантный, но он дает четкое понимание что не боги горшки обжигают.
По поводу google chrome и windows — вряд ли найдется инсайдер, который попытается тырить таким образом тостер. В случае google, отлов тостерокрадов — это вопрос доли на рынке, в случае windows — вопрос денег. Насчет linux не уверен.

Фейсбук, если мне память не изменяет, как раз и прокололся на left pad-е

А можно с этого момента поподробнее? Если вы о Babel, то он разрабатывается сейчас Генри Жу, который в Facebook не работает. Babel — обычный опен-сорс продукт, который используется фейсбуком как и многими другими.

Реакт разрабатываеся Фэйсбуком.

Попробовал поставить react в пустую папку, получил такие зависимости:


npm install react
└─┬ react@16.2.0
  ├─┬ fbjs@0.8.16
  │ ├── core-js@1.2.7
  │ ├─┬ isomorphic-fetch@2.2.1
  │ │ ├─┬ node-fetch@1.7.3
  │ │ │ ├─┬ encoding@0.1.12
  │ │ │ │ └── iconv-lite@0.4.19
  │ │ │ └── is-stream@1.1.0
  │ │ └── whatwg-fetch@2.0.3
  │ ├─┬ promise@7.3.1
  │ │ └── asap@2.0.6
  │ ├── setimmediate@1.0.5
  │ └── ua-parser-js@0.7.17
  ├─┬ loose-envify@1.3.1
  │ └── js-tokens@3.0.2
  ├── object-assign@4.1.1
  └── prop-types@15.6.0

Лефтпада здесь не вижу

История с leftpad была почти два года назад. Судя по этой статье, зависимость была.

Зависимость была в Babel, который часто ассоциируют c React, но это не так.


P.S. приводить статью Ализара в качестве пруфлинка — это сильно.

Это перевод, и вроде Ализар даже не накосячил (нда, бывает же!) =)

Перевод хоть и корректный, но все равно желтый. Ни глубокого анализа, ни проверки фактов там нет.


Но вернемся к исходной теме:


Фейсбук, если мне память не изменяет, как раз и прокололся на left pad-е.

Когда случилась проблема с left-pad, сам сайт facebook.com никуда не упал, работал как надо.


Что прошлая история, что нынешняя, описанная в статье, напоминают об одном: для стабильных и безопасных билдов храним зависимости на своей инфраструктуре, а не тянем с разных чужих доменов. Тогда у вас все будет стабильно, а все эти лефтпады, бабели и другие потенциальные проблемы будут нипочем.

Ну и в windows как-то… не знаю. В том же C# не принято тащить 150 зависимостей в проект. У нас вот немаленькая система, а nuget-пакетов всего 45, из которых 18 от Microsoft, 3 от Amazon, 5 своих, 1 коммерческий, 7 слишком хорошо известны.

Ну так вы же понимаете, что ваши 45 пакетов на самом деле каждый использует ещё кучу своих зависимостей? Просто вы их не видите, поскольку вам уже собранная библиотека приходит. По такой логике, jest это тоже один пакет. Ну и непонятно — если вы верите на слово амазону, коммерческим пакетам и "известным пакетам" — почему вы не доверяете фэйсбуку?


Это я не к тому, что нужно всем доверять, а к тому, что ситуации-то идентичные.

Ну так вы же понимаете, что ваши 45 пакетов на самом деле каждый использует ещё кучу своих зависимостей?

Нет. 45 пакетов — это уплощенное дерево, вместе с зависимостями (не считая системных dll, которые уже есть в .NET Framework на целевой машине). Так устроен nuget в .NET. Там нет "вложенных подзависимостей" (по крайней мере в той версии, кот. мы используем).


Исходя из сказанного, становится очевидно почему я не верю фейсбуку и его npm-пакетам: в их зависимостях мало ли что скрыто. В nuget и C# зависимые пакеты ставятся явно. А коль пакет тянет с собой 2 dll-ки вместо одной — то я всегда вижу что у меня подключено в References (и там далеко не 150 пунктов).

Если мне не изменяет память, нюгет в конечном итоге тащит скомпилированные dll. И что в них находится и с чем скомпилировано — одному богу известно.

Ну видимо я б-г, раз могу разобрать скомпилированную либу рефлектором (JetBrains DotPeek например):)
Если серьезно, то вкомпилить целиком одну dll-ку в другую, конечно, технически можно, но на практике никто из авторов более-менее общеизвестных пакетов этим обычно не занимается. Зависимость поставить и проще и быстрее, и установлена она будет явно. Так же авторы общеизвестных пакетов категорически не приемлют добавление еще одной зависимости в рамках pull request-а. За всех не скажу, но на моей памяти любое добавление зависимости в nuget-пакет сопровождается отчаянной битвой в комментах на гитхабе. Ну потому что когда у твоего пакета ровно 5 зависимостей, каждую из которых ты помнишь и можешь сказать зачем оно надо, то прилетевший пулл-реквест от человека, который ВНЕЗАПНО добавляет ещё одну подвергается тщательнейшему анализу на предмет а зачем оно надо, что оно делает и "может как-то можно без этого?".
Предполагаю, что когда политика всей технологии такова, что 150-200 зависимостей это нормально и плодятся они на каждый чих, то корпеть над каждой автору пакета становится физически трудновато. Ну то есть атака на npm, описанная автором в оригинальной статье — с NuGet-ом не пройдет и будет пресечена чисто на уровне дискуссии в pull request-е.

Ну видимо я б-г, раз могу разобрать скомпилированную либу рефлектором (JetBrains DotPeek например):)

Это если у вас .NET DLL. Ими мир (и даже нюгет) не ограничивается.


Предполагаю, что когда политика всей технологии такова, что 150-200 зависимостей это нормально и плодятся они на каждый чих, то корпеть над каждой автору пакета становится физически трудновато. Ну то есть атака на npm, описанная автором в оригинальной статье — с NuGet-ом не пройдет и будет пресечена чисто на уровне дискуссии в pull request-е.

Точно так же ведутся дискуссии и в мире npm. Вы почитайте как-нибудь. И поймёте, что всё в точности то же самое. Так что вероятность атаки одинаковая.

Ими мир (и даже нюгет) не ограничивается.

Само собой. Однако же поверьте, наличие native dll в нюгет-пакете вызывает как минимум оживленный интерес и вопросы "а зачем?", случается крайне редко и соответствующий пакет перед установкой пристально разглядывают. По крайней мере я так делаю.

Любая криптография, быстрые вычисления, порты нативных библиотек и так далее. Примеры искать лень. И что вы там будете разглядывать, мне интересно.

Любая криптография — это какая? CryptoPro CSP? :)
В остальном, широкий выбор криптографии уже вшит в .NET Framework, сделано MS-ом. Для быстрых вычислений так же есть unsafe mode и уж в чем-в чем, а в медленности вычислений C# замечен не был. Из всего прочего с натягом остаются порты нативных библиотек, но тут смотря что вы имеете в виду. Если, скажем, речь идет о DirectShow, то есть замечательный DirectShowNet — и в нем — сюрприз — нет никаких нативных dll. Остаются только специфические библиотеки для работы с разными устройствами, но их в Nuget обычно не выкладывают.
Словом, если вы пишете среднестатистический веб-сайтик, то вероятность того, что вы столкнетесь с нативными библиотеками стремительным домкратом летит к 0.

UFO just landed and posted this here

73 .dll-ки наблюдаю в References. Около 20 из них — системные (System.чтото, где я не вижу ни одного незнакомого имени).

UFO just landed and posted this here
UFO just landed and posted this here

С чем я вас и поздравляю, но этсамое… В оригинальной статье речь шла как раз о том, что у вас на этапе разработки 150 зависимостей (часть из этого добра вполне себе может подтягиваться вашими 23мя пакетами неявно) и через них может прокрасться вредоносный код.

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

И какие же это "нормальные языки"?


Может, Java, в которой без сторонних библиотек адекватного HTTP запроса не сделаешь?


Или C#, в котором нет нативной библиотеки для работы с JSON, и все тянут Json.NET?


Или может Go, в котором одной из популярных либ является портированная из PHP библиотека для работы со временем?


Это я уже не говорю о том, что лодаш вообще-то не является прям "часто используемой функцией", и в современном JS не так часто нужен.

UFO just landed and posted this here

Да это я просто примеров привёл навскидку. Общие функции вроде сортировки списков в JS есть, если что. У вас откуда-то взялось абсолютно неверное предположение, что в JS нет каких-то базовых вещей.

UFO just landed and posted this here

А вы сравниваете свой проект с jest — видимо, вы на питоне писали тестовый фреймворк, который должен работать на любой версии языка? Я вот у первого же попавшегося тестового фреймворка на Go вижу два десятка зависимостей с гитхаба (верхнего уровня).

А вот глядите, тестовый фреймворк на C#. 3 (три!!!) зависимости. Вместе с вложенными — 5 (пять!). Да и эти 5 — чистотехнические декомпозиционные зависимости на другие части этого же пакета от этого же автора.

А вы сравните функциональность и того и другого. Ковш для воды и ковш для экскаватора тоже вроде бы оба — ковши. Но есть нюансы.

Единственное, улавливаемое на глаз отличие — у xunit-а нет встроенных заглушек. Но для заглушек есть, например, moq, у которого из сторонних — 1 зависимость (Castle.Core).
Все еще не дотягивает до 509. :)

В C#/.NET есть встроенный функционал для работы с JSON (и с XML тоже кстати), просто Json.NET удобнее и быстрее, к тому же ни от чего не зависит. В остальном на голом C# с 0-dependency уж точно есть всё необходимое — от аналога left-pad (если он вообще кому-то нужен) и нормального API для дат (привет, Java), через встроенного клиента к HTTP/API для сокетов/трединга/асинхронности/web-а/кучи структур данных и примитивов синхронизации до встроенных клиентов к разным базам данных. А если чего-то нет, то легко руками можно выдернуть из windows API.

Да это я не в тему того, что шарп или джава чем-то плохи, а просто о том, что ни в одном языке нет полного набора необходимых и удобных конкретному разработчику модулей. Казалось бы очевидным, но видимо нет.

Само собой нет! Однако и необходимости таскать сторонние библиотеки, на каждый чих, заметьте, не возникает. Сама мысль о появлении, скажем, nuget-пакета, содержащего одну-единственную функцию добавления лидирующих символов к строке… как-то… мнэм… ну как-то так себе. С трудом представляется возможным.

Порог вхождения выше, ставить и публиковать на порядок геморройнее. Поэтому и либы сами по себе больше — всё просто. За три года писания на C# я так и не опубликовал ни одного Nuget пакета. Плюс такой довольно сомнительный.

Порог вхождения выше

Ой-вей, что я слышу! Программирование — оказывается это сложно. Кто бы мог подумать! :)


За три года писания на C# я так и не опубликовал ни одного Nuget пакета.

Ну кто ж вам виноват.


Плюс такой довольно сомнительный.

Очень хороший жирный плюс. Это значит что вы не плодили сущностей сверх необходимости (не изобретали велосипедов), не выкатывая почем зря странный код в паблик и не тратили время сообщества на его обработку, а своё — на его поддержку. При должном уровне скромности это весьма себе неплохой показатель. Или бы вы предпочли сделать что-либо, а вас бы потом тыкнули носом в уже готовые решения внутри самого .NET Framework?

Или наоборот, изобретал велосипеды сотни раз уже написанные другими, но из-за большей сложности публикации в nuget неопубликованные.

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

Конкретно left-pad уже встроен в браузеры, проблема решена (вроде бы).


О каком опыте других языков вы говорите?

Скрипты для фронтенда собирают с использованием инструментов, которые умеют выкидывать неиспользуемые функции. Так что для фронта можно импортировать лодаш и не париться — а то сначала понадобится sortBy, потом ещё что-то… И так и окажется три десятка пакетов вместо одного лодаша.


А для бэка в целом пофигу.

UFO just landed and posted this here

Тащить придётся всего лишь две реализации для разных видов данных и их зависимости (ну не так их много, правда!). Это ж прям стереотипный случай premature optimization.

А вот решение, друг мой, должно быть чисто в политической плоскости. Иными словами, дизайном standard library должна заниматься одна организация, имеющая для этих целей свой фиксированный штат квалифицированных сотрудников. При том желательно коммерческая и имеющая с качества дизайна standard library свой профит, а не какая-то странная организация-консорциум, в котором непонятно кто заседает и как ведутся дискуссии. В общем я склонен думать, что именно от такой вот "всеобщей демократии" в вопросах дизайна стандартной библиотеки мы и имеем весь действующий трэш, угар и содомию с разными функциями сортировки массивов.

UFO just landed and posted this here

Отчего же? Стандарт же есть? Есть. Как-то же договорились о наличии parseInt во всех браузерах? Ну вот же, вот, "теперь это как-то надо зазернить в катарсисе". Но ECMA тонет в дискуссиях об операторе возведения в степень вместо целенаправленной и квалифицированной проработки стандартной бибилиотеки. Тоскливо это как-то. Обидно.
Лично я это связываю с ущербностью организации самой ECMA (ну так, интуитивно), однако фактическими данными, каюсь, не владею.

UFO just landed and posted this here

Короче если бы я был президентом мира, то я бы сделал так: аки Steinberg со своим VST сделал бы стандарт для подключения конкретной реализации JavaScript к браузеру, описав бы чисто протокол. А дальше бы в рамках подключаемого модуля — пилил бы референсную реализацию. Но я чувствую, от влажности моих мечт сейчас затопит половину хабра :)
Если мыслить чуть более реалистично, то есть тащемта WebKit, хоть и будучи детищем коллективным, ИМХО в текущих реалиях вполне себе может быть взят гуглом под опеку и принят за стандарт. И типа — хотите нового в JS — идите в гугл. Но черт его знает… не уверен.

Недостаточно знаю как работает npm, чтобы утверждать, что включение в зависимости автоматически приводит к исполнению какого-то кода. В случае composer это точно не так: чтобы запустить код зависимости вам точно нужно что-то написать дополнительно, кроме банального composer require vendor/package. Если в npm достаточно npm install package и код всех пакетов будет исполняться при первом же require/import, то таки да — это хороший вектор атаки.

Уже был где-то холивар на эту тему. В npm можно сделать скрипт, который выполнится при установке пакета — так что такой вектор атаки есть. С другой стороны, это мало что значит — в любом софте вы не включаете пакет просто так — значит, вы будете его использовать. Значит, при первом же вызове он сделает своё чёрное дело.

Я именно про сценарий с пропихиванием зависимости в чей-то пакет без её реального использования. Грубо, прислать полезный реальный патч с тремя новыми зависимостями, две из которых реально используются в патче, а третий — нет.

Скорее всего, неиспользуемую зависимость выкинут из патча. Гораздо проще и логичнее сделать, чтобы она использовалась.

UFO just landed and posted this here

У нормальных разработчиков (если это не стартап 3х человек) поднято свое зеркало пакетов, и от внешних систем не зависит.


Внешние системы, бывает, падают и это нормально, если они бесплатные. Вот и Github
вчера прилег ненадолго, например

Вы последнюю неделю статус битбакета с гитхабом открывали?

Лично меня та статья напугала (стоит отметить, небезосновательно), а эта не убедила.

image
Автор той статьи явно указал на то, что исходники на гитхабе одни, а в npm идет совсем другое, минимизированное до нечитабельности, что, на мой взгляд, вполне может эксплуатироваться, если это так. Не вижу в этой статье опровержения или хотя бы упоминания этого.

В комментариях уже упоминали, что это так. И точно так же дела обстоят в maven, Nuget, и даже на самом гитхабе. А виноват опять npm.

Пожалуйста, замените все упоминания npm на Nuget и узбагойтесь.
Думаю вот эта возможность «But I’m afraid it’s perfectly possible to ship one version of your code to GitHub and a different version to npm.» является большой проблемой конкретно NPMа

Прочитайте комментарий прямо над вашим.

Я полностью согласен с тем, что система дистрибуции (npm, в данном случае) не может отвечать и, тем более, контролировать распространения каких-либо уязвимостей. Но справедливости ради, оставлю здесь эту ссылку, раз уж речь идет об обвинениях в сторону npm.
На самом деле было бы интересно увидеть какой-то положительный эффект от таких реальных или придуманных историй, в виде формулирования кем-то тезисов, а в дальнейшем, возможно, и стандартов по обеспечению безопасности систем дистрибуции openSource'а и их пользователей.

P.S. продвижки-то есть

Парольная политика это вообще общая боль, как ни странно видеть её в 2017 году в среде разработчиков.
Кстати, не знаю, как она различается в разных репозиториях — возможно npm попал под раздачу опять же из-за хайпа вокруг него.


Подвижки интересные — не знал. Спасибо. Вообще стоит опубликовать ещё и пост по тому, что делать для обеспечения большей безопасности при работе с npm — и какие есть глобальные подвижки.

Жесть какая. Впору переходить на аутентификацию по приватному ключу.

Если вы его потом случайно зальёте на гитхаб, то не поможет.


Вообще, уникальных многобайтовых паролей таки хватает. По крайней мере, пока.

Да, действительно. Но сценарий заливки ключа на гитхаб всё же не столь распространён, да и обнаружить его легко.

Sign up to leave a comment.

Articles