Анализировать зависимости NPM-пакетов можно еще с помощью Node Modules Inspector
Умеет показывать не только граф зависимостей, но и ESM/CJS поддержку, использование транзитивных зависимостей, место на диске.
https://node-modules.dev/
Умеет показывать не только граф зависимостей, но и ESM/CJS поддержку, использование транзитивных зависимостей, место на диске.
https://node-modules.dev/
Насколько мне известно, появление поиска в ChatGPT, Google Grounding Answers, Claude Web Search сильно меняет рынок поисковиков.
Все больше пользователей ищут ответы на свои вопросы через AI, не утруждая себя подбором ключевых слов в Google.
Но насколько поиск через AI действительно лучше?
Автор проводит ревью существующих инструментов, рассуждает, как можно улучшить текущий поиск и какие у него есть проблемы.
https://paulstamatiou.com/browse-no-more
Все больше пользователей ищут ответы на свои вопросы через AI, не утруждая себя подбором ключевых слов в Google.
Но насколько поиск через AI действительно лучше?
Автор проводит ревью существующих инструментов, рассуждает, как можно улучшить текущий поиск и какие у него есть проблемы.
https://paulstamatiou.com/browse-no-more
Forwarded from amorgunov
Уязвимости в NextJS
Я думаю уже почти все слышали про уязвимость в NextJS, которая позволяет при запросах обходить миддлевары, и например, пропускать обработку авторизационных токенов и прочие серверные проверки. Уязвимость очень проста в эксплуатации, достаточно прокинуть http-заголовок
Наш проект это не затронуло, так как мы не смогли в свое время завести в нашей инфре стабильную работу миддлевар. Но пару месяцев назад мы столкнулись с другой уязвимостью на основе «cache poisoning», которая не получила столь бурную реакцию в интернете, но в нашем случае тоже могла бы привести к довольно критичным последствиям.
Cache poisoning (дословно, отравление кэша) - это атака, при которой обычным пользователям отображается вредоносный ответ на основе манипуляций с веб-сервером и кэшем.
Кэш позволяет отдавать идентичный ответ пользователю, который сделал аналогичный запрос. Как понять, что запрос аналогичный? У запросов должен быть одинаковый кэш-ключ, который обычно формируется на основе различных компонентов: тип запроса, хост, pathname, некоторые http-заголовки (конечно этих параметров может быть намного больше). Если ключ совпадает, то отдается сохраненный результат из кэша, если нет - то запрос начинает обрабатываться сервером.
Но есть компоненты, которые никак не влияют на ключ кэша (например какие-нибудь http-заголовки). И если какой-нибудь из этих компонентов может повлиять на ответ, то можно подложить отравленный результат в кэш, который будет возвращаться уже обычным пользователям.
Вот и мы нарвались на такую уязвимость в нексте (CVE-2024-46982). Если кратко, у NextJS в рамках page router-а есть режим SSR через функцию
Сам по себе
Более того, в этот JSON часто попадают значения http-заголовков, поэтому в него можно положить произвольный текст. А с учетом того, что запросы продолжают отдавать content-type равный text/html, то получаем еще и XSS абсолютно для всех пользователей, которые просто зайдут на страницу.
Подробнее про это можете почитать в блоге все того же профессора Рашида https://zhero-web-sec.github.io/research-and-things/nextjs-cache-and-chains-the-stale-elixir
Уязвимость уже была пофикшена в новых версиях NextJS, поэтому для фикса нам нужно было апнуть минорную версию, но это уже другая история.
Я думаю уже почти все слышали про уязвимость в NextJS, которая позволяет при запросах обходить миддлевары, и например, пропускать обработку авторизационных токенов и прочие серверные проверки. Уязвимость очень проста в эксплуатации, достаточно прокинуть http-заголовок
x-middleware-subrequest
, которая пропускает указанные миддлевары. Подробнее почитать можно в блоге Рашида Алама.Наш проект это не затронуло, так как мы не смогли в свое время завести в нашей инфре стабильную работу миддлевар. Но пару месяцев назад мы столкнулись с другой уязвимостью на основе «cache poisoning», которая не получила столь бурную реакцию в интернете, но в нашем случае тоже могла бы привести к довольно критичным последствиям.
Cache poisoning (дословно, отравление кэша) - это атака, при которой обычным пользователям отображается вредоносный ответ на основе манипуляций с веб-сервером и кэшем.
Кэш позволяет отдавать идентичный ответ пользователю, который сделал аналогичный запрос. Как понять, что запрос аналогичный? У запросов должен быть одинаковый кэш-ключ, который обычно формируется на основе различных компонентов: тип запроса, хост, pathname, некоторые http-заголовки (конечно этих параметров может быть намного больше). Если ключ совпадает, то отдается сохраненный результат из кэша, если нет - то запрос начинает обрабатываться сервером.
Но есть компоненты, которые никак не влияют на ключ кэша (например какие-нибудь http-заголовки). И если какой-нибудь из этих компонентов может повлиять на ответ, то можно подложить отравленный результат в кэш, который будет возвращаться уже обычным пользователям.
Вот и мы нарвались на такую уязвимость в нексте (CVE-2024-46982). Если кратко, у NextJS в рамках page router-а есть режим SSR через функцию
getServerSideProps
, которая подготавливает данные в формате JSON для страницы. Для этого некст при заходе на страницу отправляет запрос по пути /_next/data/...
. Но есть внутренний query-параметр ?__nextDataReq=1
, при добавлении которого к странице возвращается только JSON-данные для нее. И этот query-параметр не является частью ключа для кэша. Условно https://a.com
и https://a.com/?__nextDataReq=1
будут иметь один ключ. Если результат второго запроса сложить в кэш, то у всех пользователей вместо главной страницы будет открываться JSON с данными.Сам по себе
getServerSideProps
является динамическим и в кэш ничего не складывает. Но еще есть внутренний http-заголовок x-now-route-matches
, "включающий" SSG (server side generation) режим некста, который складывает результаты в кэш. Понимаете к чему я веду? Уязвимость заключается именно в этом и с помощью комбинации ?__nextDataReq=1
+ x-now-route-matches
и одного запроса можно сломать любую динамическую страницу приложения, путем складывания в кэш JSON-данных для страницы и отдачи их вместо html-контента.Более того, в этот JSON часто попадают значения http-заголовков, поэтому в него можно положить произвольный текст. А с учетом того, что запросы продолжают отдавать content-type равный text/html, то получаем еще и XSS абсолютно для всех пользователей, которые просто зайдут на страницу.
Подробнее про это можете почитать в блоге все того же профессора Рашида https://zhero-web-sec.github.io/research-and-things/nextjs-cache-and-chains-the-stale-elixir
Уязвимость уже была пофикшена в новых версиях NextJS, поэтому для фикса нам нужно было апнуть минорную версию, но это уже другая история.
Forwarded from BEARlogin Dev
Блокировки, блокировки, блокировочки...
Значит, бывает такая история, что сидишь ты понимаешь, на хорошем и дешевом хостинге и крутиш свои кубернейтесы. И все тебе збс и устраивает.
Но вот не задача, почему то (sarcasm) подсети этого хостинга начинают блочить провайдеры...
Смачно выругавшись начинаем искать варианты:
1. Переехать значит на православный хостинг и платить x100500 деняг
2. Купить на православном хостинге VPS, поставить там nginx в режиме stream и надеяться, что хостинг не заблокируют на уровне магистрали.
Для тех кто выбрал второй вариант, все просто.
1. Ставим nginx с поддержкой stream
2. Добавляем в nginx.conf
В отличие от стандартного http {} блока, stream работает на уровне TCP, а не HTTP.
Он не трогает заголовки, не читает Host, не парсит User-Agent
Он просто берёт входящий TLS-трафик и тупо прокидывает его дальше.
При этом это работает охуительно быстро, в отличии от обычного proxy_pass
Никакого overhead, никакой нагрузки на CPU, ничего не разбирается, не кешируется и не мутируется.
Это как туннель, только без OpenVPN и танцев с бубном.
BEARlogin dev — подпишись!
#блокировки #proxy #devops
Значит, бывает такая история, что сидишь ты понимаешь, на хорошем и дешевом хостинге и крутиш свои кубернейтесы. И все тебе збс и устраивает.
Но вот не задача, почему то
Смачно выругавшись начинаем искать варианты:
1. Переехать значит на православный хостинг и платить x100500 деняг
2. Купить на православном хостинге VPS, поставить там nginx в режиме stream и надеяться, что хостинг не заблокируют на уровне магистрали.
Для тех кто выбрал второй вариант, все просто.
1. Ставим nginx с поддержкой stream
2. Добавляем в nginx.conf
...
stream {
upstream k8s_https {
server ваш_ip:443;
}
server {
listen 443;
proxy_pass k8s_https;
}
}
...
В отличие от стандартного http {} блока, stream работает на уровне TCP, а не HTTP.
Он не трогает заголовки, не читает Host, не парсит User-Agent
Он просто берёт входящий TLS-трафик и тупо прокидывает его дальше.
При этом это работает охуительно быстро, в отличии от обычного proxy_pass
Никакого overhead, никакой нагрузки на CPU, ничего не разбирается, не кешируется и не мутируется.
Это как туннель, только без OpenVPN и танцев с бубном.
BEARlogin dev — подпишись!
#блокировки #proxy #devops
Еще один день, когда приложение ChatGPT просто выкидывает записанный войс, потому что транскрибировать не удалось.
Гениальное решение, ну раз юзер записал войс, значит сама запись больше не нужна, не взирая на возможные ошибки распознавания… гении, не иначе
Гениальное решение, ну раз юзер записал войс, значит сама запись больше не нужна, не взирая на возможные ошибки распознавания… гении, не иначе
Не понимаю я людей, которые считают, что мы одни во вселенной.
Вот смотришь на такие фото, там сотни галактик, и очень давно и далеко.
Мы, как вид, не можем выяснить, есть ли жизнь на другой планете в пределах нашей собственной галактики, а так уверенно утверждать про целую вселенную…
То, что мы не нашли, еще не значит, что жизни нет.
Я почти уверен, что вселенная полна жизни в самых разных формах.
Вот смотришь на такие фото, там сотни галактик, и очень давно и далеко.
Мы, как вид, не можем выяснить, есть ли жизнь на другой планете в пределах нашей собственной галактики, а так уверенно утверждать про целую вселенную…
То, что мы не нашли, еще не значит, что жизни нет.
Я почти уверен, что вселенная полна жизни в самых разных формах.
Forwarded from Effector news (Sergey Sova)
atomic-router v0.12
- Экспортирован тип
- Минимальная версия Node.JS поднята до v18.x
atomic-router-react v0.12
- Минимальная версия Node.JS поднята до v18.x
- Минимальная версия atomic-router теперь v0.12.0
- Удален
- Добавлен параметр replace в Link —
- Добавлена поддержка React 19
P.S.
С точки зрения поведения брейкингов не было.
Все найденные баги репортите в репозитории пожалуйста.
В ближайшее время занимаюсь фиксами всех уже найденных.
- Экспортирован тип
HistoryRouter
- Минимальная версия Node.JS поднята до v18.x
atomic-router-react v0.12
- Минимальная версия Node.JS поднята до v18.x
- Минимальная версия atomic-router теперь v0.12.0
- Удален
atomic-router-react/scope
, так как effector-react
теперь работает со Scope из коробки- Добавлен параметр replace в Link —
<Link replace>
- Добавлена поддержка React 19
P.S.
С точки зрения поведения брейкингов не было.
Все найденные баги репортите в репозитории пожалуйста.
В ближайшее время занимаюсь фиксами всех уже найденных.
Уже несколько лет пользуюсь @trivago/prettier-plugin-sort-imports для быстрой сортировки импортов через prettier.
В какой-то момент убрали лишнюю зависимость от @vue/compiler-sfc, пользоваться стало совсем приятно.
Вот мой конфиг, который обычно переношу из проекта в проект.
В какой-то момент убрали лишнюю зависимость от @vue/compiler-sfc, пользоваться стало совсем приятно.
Вот мой конфиг, который обычно переношу из проекта в проект.
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"trailingComma": "all",
"bracketSpacing": true,
"plugins": ["@trivago/prettier-plugin-sort-imports"],
"importOrderGroupNamespaceSpecifiers": true,
"importOrderParserPlugins": ["typescript", "jsx"],
"importOrderSortSpecifiers": true,
"importOrderSeparation": true,
"importOrder": [
"<THIRD_PARTY_MODULES>",
"^@/app(.*)$",
"^@/pages(.*)$",
"^@/layouts(.*)$",
"^@/widgets(.*)$",
"^@/features(.*)$",
"^@/entities(.*)$",
"^@/shared(.*)$",
"^[../]",
"^[./]"
]
}
А вот совсем недавно обнаружил форк, который добавляет еще несколько опций поверх плагина от Trivago.
https://github.com/ianvs/prettier-plugin-sort-imports
1. Добавляет специальные группы
2. Возможность разделять группы через
Но вот этих опций нет
И если с
Тестирую с этим конфигом:
https://github.com/ianvs/prettier-plugin-sort-imports
1. Добавляет специальные группы
<BUILTIN_MODULES>
и <TYPES>
;2. Возможность разделять группы через
""
;Но вот этих опций нет
"importOrderSortSpecifiers": true,
"importOrderSeparation": true,
И если с
order separation
всё понятно, теперь добавляем ""
и живём, то вот с sort specifiers
пока непонятно.Тестирую с этим конфигом:
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"trailingComma": "all",
"bracketSpacing": true,
"plugins": ["@ianvs/prettier-plugin-sort-imports"],
"importOrder": [
"<BUILTIN_MODULES>",
"<THIRD_PARTY_MODULES>",
"",
"^@/app(.*)$",
"^@/pages(.*)$",
"^@/layouts(.*)$",
"^@/widgets(.*)$",
"^@/features(.*)$",
"^@/entities(.*)$",
"^@/shared(.*)$",
"",
"^[../]",
"^[./]"
],
"importOrderParserPlugins": ["typescript", "jsx"],
"importOrderTypeScriptVersion": "5.0.0",
"importOrderCaseSensitive": false
}
Много лет пользовался husky + lint-staged, недавно во время подготовки тестового задания попробовал lefthook.
Во первых, приятно, что он заменяет собой сразу две зависимости.
Во вторых, простой, но при этом супер гибкий в настройке.
Ну и наконец, в CLI приятно выглядит, просто как бонус.
Во первых, приятно, что он заменяет собой сразу две зависимости.
Во вторых, простой, но при этом супер гибкий в настройке.
Ну и наконец, в CLI приятно выглядит, просто как бонус.
pre-push:
jobs:
- name: packages audit
run: pnpm audit
- name: build
run: pnpm build
pre-commit:
commands:
eslint:
run: pnpm eslint {staged_files} --fix
glob: "*.{js,ts,jsx,tsx}"
stage_fixed: true
prettier:
run: pnpm prettier --write {staged_files}
glob: "*.{js,ts,jsx,tsx,css,html,json}"
stage_fixed: true
А оказывается, Node.js 24 поддерживает синтаксис
Что позволяет сделать даже логи проще и приятнее.
Когда
Хоть изначально предназначено для очистки ресурсов, но здесь хорошо работает
https://github.com/tc39/proposal-explicit-resource-management
using
Что позволяет сделать даже логи проще и приятнее.
Когда
mainGroup
выйдет из скоупа (функция, if, for или {}), автоматически будет вызвана функция [Symbol.dispose]
Хоть изначально предназначено для очистки ресурсов, но здесь хорошо работает
https://github.com/tc39/proposal-explicit-resource-management
Плавный переезд Vite на Rolldown
https://voidzero.dev/posts/announcing-rolldown-vite
Ещё один инструмент фронтендеров уходит с JavaScript runtime на Rust.
С одной стороны это обосновано, там какие-то нереальные цифры профита по производительности и по памяти, а с другой уходят не полностью.
Нельзя просто так взять и отказаться от огромной экосистемы JavaScript-плагинов Rollup — в сборщике есть JavaScript движок, чтобы их запускать.
Меня радует, что авторы обещают отсутствие мажорных отличий. Конечно, для популярных плагинов/фреймворков этот переезд не критичен — баги быстро пофиксят, а критичные места можно покрыть через
А вот для кастомных плагинов, если они у вас есть, может возникнуть проблема. Поэтому лично я начну тестировать rolldown-vite на своих проектах уже в ближайшее время.
Благо это крайне легко:
https://voidzero.dev/posts/announcing-rolldown-vite
Ещё один инструмент фронтендеров уходит с JavaScript runtime на Rust.
С одной стороны это обосновано, там какие-то нереальные цифры профита по производительности и по памяти, а с другой уходят не полностью.
Нельзя просто так взять и отказаться от огромной экосистемы JavaScript-плагинов Rollup — в сборщике есть JavaScript движок, чтобы их запускать.
Меня радует, что авторы обещают отсутствие мажорных отличий. Конечно, для популярных плагинов/фреймворков этот переезд не критичен — баги быстро пофиксят, а критичные места можно покрыть через
if(vite.rolldownVersion)
А вот для кастомных плагинов, если они у вас есть, может возникнуть проблема. Поэтому лично я начну тестировать rolldown-vite на своих проектах уже в ближайшее время.
Благо это крайне легко:
{
"pnpm": {
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}
}