Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
sloppy-joe — Защищает от атак на цепочку поставок, слопсквоттинга и тайпсквоттинга со стороны зависимостей и кода. | Kitploit
Инструменты/GitHubGitHub/brennhill/sloppy-joe
Статический анализСканеры уязвимостейАнализ КодаDevSecOpsОбнаружение СекретовРазведка угрозБезопасность Цепочки ПоставокОбучение и Образование
GitHubbrennhill/sloppy-joe

sloppy-joe

Защищает от атак на цепочку поставок, слопсквоттинга и тайпсквоттинга со стороны зависимостей и кода.

Репозиторий
3214 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

sloppy-joe

Ловите галлюцинированные, typosquatted и неканонические зависимости
до того, как они попадут в продакшен.

cargo install sloppy-joe


Атака на цепочку поставок LiteLLM (март 2026) скомпрометировала пакет с 97 млн загрузок в месяц. Злоумышленники украли учетные данные для публикации, выложили вредоносные версии, которые собирали SSH-ключи, облачные учетные данные и секреты Kubernetes. Встроенная 72-часовая задержка по возрасту версий в sloppy-joe заблокировала бы обе отравленные версии — они были обнаружены в течение нескольких часов, задолго до того, как заслонка открылась бы. Если вы запускаете sloppy-joe check в CI, эта атака проваливается. Полный анализ

Генераторы ИИ-кода галлюцинируют имена пакетов примерно в 20% случаев. Злоумышленники регистрируют эти имена и ждут. sloppy-joe ловит их в CI до того, как будет выполнено npm install или pip install.

Как использовать```bash

Install (single static binary, no runtime dependencies)

cargo install sloppy-joe

Or download an auditable binary archive from GitHub Releases

https://github.com/brennhill/sloppy-joe/releases

Fast local guardrail — auto-detects ecosystem from manifest files

sloppy-joe check

Strict online scan (recommended before push / release)

sloppy-joe check --full

Strict CI-oriented scan

sloppy-joe check --ci

Check a specific directory

sloppy-joe check --dir ./my-project

Check only npm dependencies

sloppy-joe check --type npm

Check the Python runtime plus selected groups/extras

sloppy-joe check --python-groups dev,test --python-version 3.12 sloppy-joe check --python-extras docs --python-platform linux --python-version 3.12

Enforce canonical rules and org standards via config

sloppy-joe check --config /etc/sloppy-joe/config.json

Config from a URL (useful in CI — no secrets to manage)

sloppy-joe check --config https://raw.githubusercontent.com/yourorg/security-configs/main/sloppy-joe.json

JSON output for CI pipelines

sloppy-joe check --json

Review exact maintainer-change exceptions with evidence

sloppy-joe check --review-exceptions

Create and register a safe per-repo config outside the repo

sloppy-joe init --register

Create an ecosystem-specific greenfield starter policy

sloppy-joe init --greenfield --ecosystem npm

Print review-only bootstrap suggestions for an npm or Cargo repo

sloppy-joe init --from-current

Or write/register those suggestions safely outside the repo

sloppy-joe init --from-current --register

Or write a config manually to a secure path outside the repo

sloppy-joe init > /secure/location/sloppy-joe.json

root@kitploit:~
### Nix```bash
nix profile install github:brennhill/sloppy-joe

Режимы сканирования:

  • sloppy-joe check запускает быстрый локальный барьер (guardrail). Он всегда применяет политики разбора манифеста, блокировки/синхронизации, подтверждения происхождения (provenance) и неподдерживаемых источников. Если изменилось состояние зависимостей или политики, или последняя успешная полная проверка была больше 24 часов назад, выводится рекомендация sloppy-joe check --full.
  • sloppy-joe check --full запускает строгую онлайн-проверку и обновляет запись состояния успешной полной проверки.
  • sloppy-joe check --ci выполняет то же строгое покрытие, что и --full, но с ориентацией на CI.
  • Для Python sloppy-joe check по умолчанию оценивает профиль runtime. Если существуют уточнённые зависимости, выводится предупреждение с указанием передать явные флаги --python-groups, --python-extras, --python-platform и/или --python-version для паритета с CI/сборкой.
  • Человекочитаемый вывод всегда напоминает использовать или для CI и продуктового шлюза (production gating).

Коды выхода: 0 = в выбранном режиме проблем, блокирующих выполнение, не найдено, 1 = найдены блокирующие проблемы, 2 = ошибка выполнения.

Поддержка: JavaScript (npm, pnpm, Yarn, Bun), Python, Rust, Go, Ruby, PHP, JVM (Gradle/Maven) и .NET — автоматическое определение по файлам манифеста.

Путеводители по экосистемам: см. docs/ecosystems/README.md для текущей модели доверия, поддерживаемых функций и ограничений режима «fail-closed» для каждой экосистемы.

  • JavaScript
  • Python
  • Rust
  • Go
  • Ruby
  • PHP / Composer
  • JVM
  • .NET / NuGet

Источники конфигурации: локальный путь к файлу, URL по HTTPS или переменная окружения SLOPPY_JOE_CONFIG. Конфигурация никогда не считывается из каталога проекта (см. CONFIG.md почему).

Начало работы (Onboarding): используйте режим начальной настройки, соответствующий репозиторию:

  • sloppy-joe init --greenfield --ecosystem <eco> выводит стартовую политику для нового проекта, специфичную для экосистемы. Сегодня заготовки greenfield реализованы для npm, pypi и cargo; для других экосистем команда завершается ошибкой «not supported yet». Добавьте --register, чтобы записать её за пределами репозитория и зарегистрировать безопасно.
  • sloppy-joe init --from-current проверяет текущий репозиторий и выводит предложения начальной настройки только для просмотра (review-only). Сегодня --from-current реализован только для репозиториев, чей собственный код является npm и/или cargo; для других экосистем команда завершается ошибкой «not implemented yet». Добавьте --register, чтобы записать и зарегистрировать сгенерированную конфигурацию.
  • sloppy-joe init без режима выводит нейтральный шаблон для ручной настройки.

Зачем sloppy-joe?

Один бинарный файл. 8 экосистем. 16 типов атак. Ноль ложных срабатываний на генеративных проверках. Конфигурация, которую AI-агенты не могут подделать.

Большинство инструментов безопасности зависимостей проверяют одну-две вещи — существует ли пакет или расстояние редактирования. sloppy-joe проверяет 16 векторов атак за один проход: галлюцинированные пакеты, 10 типов тайпсквоттинга (гомоглифы, захват области видимости, повторяющиеся символы, путаница с разделителями, перестановка слов, соседние обмены, пропущенные символы, спутанные формы, варианты регистра, суффиксы версий), контроль каноничности, шлюз по возрасту версии, усиление скриптов установки, взрыв зависимостей, смена мейнтейнера и известные уязвимости через OSV.dev.

Он работает как единый Rust-бинарник без зависимостей времени выполнения. Поддерживает все 8 основных экосистем пакетов. А его конфигурация спроектирована для безопасности: никогда не считывается из каталога проекта, может загружаться через URL для CI, с понятными сообщениями об ошибках, когда что-то не так.

🔶 = бета/экспериментальная


Как работает каждая атака (и как sloppy-joe её блокирует)

1. Галлюцинированные пакеты

Атака: ИИ генерирует import ai_json_helper. Пакета не существует. Злоумышленник регистрирует ai-json-helper на PyPI с вредоносным кодом. В следующий раз, когда кто-то запустит pip install, будет установлен вредоносный пакет.

Как sloppy-joe блокирует: Проверка существования обращается к API PyPI и получает 404. Сборка блокируется.``` ERROR ai-json-helper [existence] Package 'ai-json-helper' does not exist on the pypi registry. It may be hallucinated by an AI code generator. Fix: Remove 'ai-json-helper' from your dependencies.

root@kitploit:~
### 2. Тайпсквоттинг (генеративные проверки + резервное расстояние Левенштейна)

**Атака:** Злоумышленник регистрирует `expresz` в npm — на один символ отличается от `express`. ИИ генерирует его, или разработчик случайно ошибается в наборе. Пакет существует, проходит проверку на существование и устанавливает вредоносное ПО.

**Как sloppy-joe это блокирует:** sloppy-joe запускает 10 генеративных проверок перед переходом к расстоянию редактирования. Каждая генеративная проверка создаёт специфическую мутацию имени зависимости (меняет местами символы, схлопывает повторения, удаляет суффиксы, переупорядочивает слова, нормализует разделители, заменяет гомоглифы, проверяет области видимости) и проверяет точное совпадение с известными популярными пакетами. Этот подход, вдохновлённый библиотекой [Rust Foundation's Typomania](https://github.com/rustfoundation/typomania), имеет почти нулевой уровень ложных срабатываний, поскольку срабатывает только при точных совпадениях после мутации.

Расстояние Левенштейна выполняется последним в качестве страховочной сети для новых мутаций, которые не были предусмотрены ни одной конкретной проверкой. Вместе они покрывают как известные шаблоны атак (точно), так и неизвестные (в целом).```
ERROR expresz [similarity/edit-distance]
      'expresz' is 1 character away from 'express'. This could be a typosquat.
 Fix: If you meant 'express', fix the name in your manifest.

3. Повторяющиеся символы

Атака: expresss (лишняя s) или reeact (лишняя e). Это распространенные шаблоны галлюцинаций ИИ — модель генерирует правдоподобные названия с повторяющимися символами.

Как sloppy-joe блокирует это: Проверка повторяющихся символов удаляет по одному дубликату за раз и проверяет, соответствует ли результат известному пакету. expresss → удаляем одну s → express → совпадение.``` ERROR expresss [similarity/repeated-chars] 'expresss' matches 'express' after removing a repeated character. Fix: Use 'express' — remove the repeated characters.

root@kitploit:~
### 4. Путаница с разделителями

**Атака:** `python-dateutil` vs `python_dateutil` vs `pythondateutil`. В некоторых реестрах это разные пакеты. Злоумышленник регистрирует вариант.

**Как sloppy-joe блокирует это:** Нормализует все разделители (`-`, `_`, `.`) перед сравнением. Если нормализованная форма совпадает с известным пакетом, он помечается.```
ERROR socket_io [similarity/separator-confusion]
      'socket_io' matches 'socket.io' after normalizing separators.
 Fix: Use the canonical name 'socket.io' with the correct separators.

5. Перестановка слов

Атака: parse-json vs json-parse. Расстояние Левенштейна равно 8 — невидимо для проверок расстояния редактирования. Но злоумышленник может зарегистрировать переставленное имя.

Как sloppy-joe это блокирует: Разделяет по разделителям, генерирует все перестановки сегментов и проверяет каждую по корпусу. parse-json → перестановка → json-parse → совпадение.``` ERROR parse-json [similarity/word-reorder] 'parse-json' is a reordering of 'json-parse'. Fix: Use 'json-parse' — the segments are in the wrong order.

root@kitploit:~
### 6. Перестановки соседних символов

**Атака:** `reqeust` вместо `request`. Два соседних символа переставлены местами — распространённая опечатка, которую атакующие используют в своих целях.

**Как sloppy-joe блокирует это:** Генерирует все варианты перестановок соседних символов имени зависимости и проверяет каждый по корпусу.```
ERROR reqeusts [similarity/char-swap]
      'reqeusts' matches 'requests' with two adjacent characters swapped.
 Fix: Use 'requests' — two characters are transposed.

7. Пропущенные символы

Атака: reqests (пропущен u) вместо requests. ИИ пропускает символ, и результат выглядит как валидное имя.

Как sloppy-joe блокирует это: Вставляет каждый символ a-z на каждую позицию в имени и проверяет, соответствует ли какой-либо результат известному пакету. reqests + u на позиции 3 → requests → совпадение.``` ERROR reqests [similarity/omitted-char] 'reqests' matches 'requests' with one character inserted. Fix: Use 'requests' — a character appears to be missing.

root@kitploit:~
### 8. Омоглифы (визуально похожие символы)

**Атака:** `rеquests` с кириллической `е` (U+0435) вместо латинской `e` (U+0065). Визуально идентично. Имя пакета выглядит в точности как `requests`, но ссылается на другой, вредоносный пакет.

**Как sloppy-joe блокирует это:** Заменяет 17 известных омоглифов (кириллица, полноширинные символы, варианты прописных) на их латинские эквиваленты и проверяет, совпадает ли результат с известным пакетом.```
ERROR rеquests [similarity/homoglyph]
      'rеquests' contains characters that look identical to 'requests'
      but are different Unicode codepoints (homoglyphs).
 Fix: Replace the lookalike characters with standard ASCII.

9. Запутанные формы в экосистеме

Атака: py-utils против python-utils. На PyPI это разные пакеты. ИИ генерирует один, когда вы имели в виду другой. Аналогично, github.com против gitlab.com в модулях Go.

Как sloppy-joe блокирует это: Применяет специфические для экосистемы правила подстановки (py↔python для PyPI, github↔gitlab для Go) и проверяет, не соответствует ли какой-либо вариант известному пакету.``` ERROR py-flask [similarity/confused-form] 'py-flask' is a confused form of 'flask'. Fix: Use the canonical name 'flask'.

root@kitploit:~
### 10. Атаки с использованием вариантов регистра (чувствительные к регистру реестры)

**Атака:** В Go, Maven и Ruby пакеты `Rails` и `rails` считаются разными. Злоумышленник регистрирует вариант с заглавной буквы.

**Как sloppy-joe блокирует это:** В реестрах, чувствительных к регистру, любой вариант регистра известного пакета помечается как ошибка. В реестрах, не чувствительных к регистру (npm, PyPI, Cargo, NuGet, PHP), варианты регистра безопасны и пропускаются.```
ERROR Rails [similarity/case-variant]
      'Rails' differs from 'rails' only in letter casing.
      On case-sensitive registries (ruby) these resolve to different packages.
 Fix: Use the exact casing 'rails' in your manifest.

11. Сквоттинг суффикса версии

Атака: requests2 или lodash-4. ИИ добавляет номер версии к имени пакета вместо правильного указания версии.

Как sloppy-joe блокирует это: Удаляет конечные цифры и разделители и проверяет, соответствует ли базовое имя известному пакету.``` ERROR requests2 [similarity/version-suffix] 'requests2' looks like 'requests' with a version suffix appended. Fix: Use 'requests' and specify the version in your manifest's version field.

root@kitploit:~
### 12. Сквоттинг области видимости (npm, PHP, Go, JVM)

**Атака:** Злоумышленник регистрирует `@typos/lodash` в npm — на одну букву от `@types/lodash`. Или `larvael/framework` на Packagist — на две буквы от `laravel/framework`. Или `github.com/gooogle/protobuf` в Go — одна лишняя `o`. Область видимости с первого взгляда выглядит легитимной. Пакет устанавливается. Вредоносное ПО внедряется.

Это редко, но возможно — и именно для таких случаев существует sloppy-joe. Инцидент с `ua-parser-js` в 2021 году был связан с областью видимости. Если это может случиться с пакетом с миллионами еженедельных загрузок, это может случиться и с вашим.

**Как sloppy-joe это блокирует:** Извлекает область видимости/пространство имен из имени зависимости и сравнивает его со списком известных доверенных областей с помощью расстояния редактирования. Работает для npm (`@scope`), PHP (`vendor/`), Go (`github.com/org`) и JVM (`com.group`).```
ERROR @typos/lodash [similarity/scope-squatting]
      Scope '@typos' is 1 character away from the known scope '@types'.
      Scope squatting is a known supply chain attack vector.
 Fix: If you meant '@types/lodash', fix the scope in your manifest.

| --discover-timeout | No | При назначении портов целям время ожидания в миллисекундах до истечения тайм-аута. 0 означает бесконечное ожидание. | 0 | | --max-depth | No | Максимальная глубина поиска шаблонов файлов. Поддерживаются отрицательные числа. -1 означает отсутствие ограничений. | -1 | | --stats | No | Отображение статистики выполняемого сканирования | false | | --stats-json | No | Запись статистики в файл в формате JSONL(ines) | false | | --stats-interval | No | Интервал в секундах для отображения/записи статистики. 0 отключает. | 5 | | --metrics | No | Предоставлять метрики nucleus на указанном порту. | | | | No | Порт, на котором предоставлять метрики nucleus. | | | | No | Отключить вывод HTTP-ответа, показывать только результаты и вывод в STDOUT | | | | No | Включить пассивную обработку HTTP-ответов | | | | No | Разрешить использование переменных окружения в шаблоне | | | | No | Показать дамп переменных для отладки. | | | | No | Включить загрузку шаблонов, основанных на протоколе code. | | | | No | Принудительно использовать HTTP2 для всех HTTP-запросов. | | | | No | Отключить обработку стандартного ввода. | | | | No | Настроить клиентский сертификат для аутентификации с целевым объектом сканирования. Поддерживаются форматы , , . | | | | No | Настроить центр сертификации для аутентификации с целевым объектом сканирования. Поддерживаются форматы , , . | | | | No | Использовать библиотеку ZTLS с автоматическим переходом на стандартную для расширенной обработки TLS. | | | | No | Использовать библиотеку ZTLS с возможностью перехода на стандартную библиотеку TLS. | | | | No | (Экспериментальный) Принудительно использовать пользовательский SNI для TLS-соединений через ZTLS. | `` |``` ERROR github.com/gooogle/protobuf [similarity/scope-squatting] Scope 'github.com/gooogle' is 1 character away from 'github.com/google'. Fix: If you meant 'github.com/google/protobuf', fix the org name.

root@kitploit:~
### 13. Неканонические пакеты (не атака — шлюз согласованности)

**The attack:** Не атака — проблема согласованности. ИИ выбирает `moment`, потому что он был популярен в обучающих данных, но ваша команда использует `dayjs`. Разные команды, использующие разные пакеты для одной и той же задачи, создают долг по обслуживанию и разбухание зависимостей.

**How sloppy-joe blocks it:** Ваша конфигурация сопоставляет каждый канонический пакет с его отклоненными альтернативами. Если зависимость совпадает с альтернативой, сборка завершается неудачей.```
ERROR moment [canonical]
      'moment' is not the approved package for this purpose.
      Your team uses 'dayjs'.
 Fix: Replace 'moment' with 'dayjs' in your manifest file.

14. Слишком новые версии (бомба замедленного действия в цепочке поставок)

Атака: Злоумышленник взламывает учетную запись мейнтейнера пакета (или мейнтейнер становится мошенником) и публикует вредоносную версию патча. Она выглядит как обычное обновление. Если ваш CI сразу же установит её, вы будете скомпрометированы до того, как кто-либо заметит.

Как sloppy-joe блокирует это: Шлюз возраста версии блокирует любую зависимость, версия которой была опубликована менее min_version_age_hours часов назад (по умолчанию: 72 часа). Это дает сообществу, Socket.dev и другим сканерам время пометить вредоносные версии.``` ERROR react [metadata/version-age] Version '^19.0.0' of 'react' was published 6 hours ago (minimum: 72 hours). New versions need time for the community and security scanners to review them. Fix: Wait until the version is at least 72 hours old, or pin to an older version.

root@kitploit:~
### 15. Совершенно новые пакеты

**Атака:** Пакет, созданный вчера, с 3 загрузками, имя которого похоже на популярный пакет. Высокая вероятность того, что это тайпсквот или заполнитель для будущей атаки.

**Как sloppy-joe блокирует это:** Помечает любой пакет, созданный менее 30 дней назад.```
ERROR sketchy-lib [metadata/new-package]
      'sketchy-lib' was first published 2 days ago.
      New packages are higher risk.
 Fix: Verify 'sketchy-lib' at its registry page and source repository.

16. Пакеты с низким числом загрузок

Атака: Пакет с 12 загрузками, который отличается на один символ от requests. Почти наверняка это опечатка (typosquat).

Как sloppy-joe блокирует это: Помечает пакеты с количеством загрузок менее 100 (там, где реестр предоставляет данные о загрузках — в настоящее время npm, crates.io, RubyGems).``` ERROR requsets [metadata/low-downloads] 'requsets' has only 12 downloads. Fix: Verify 'requsets' is the package you intend to use.

root@kitploit:~
---

## Поддерживаемые экосистемы

| Экосистема | Манифест | Политика лок-файлов | Существование | Метаданные | Возрастной шлюз |
|-----------|----------|-----------------|:---------:|:--------:|:--------:|
| npm | package.json | Требуется `package-lock.json` или `npm-shrinkwrap.json` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PyPI | `pyproject.toml`, `requirements*.txt`, `Pipfile`, `setup.cfg`, `setup.py` | Poetry доверен с `poetry.lock`, uv доверен с `uv.lock`, полностью хэш-блокированный pip-tools доверен только когда зафиксированный граф зависимостей привязывает `--index-url` и точные разрешённые значения `--extra-index-url`, а видимые в репозитории пользовательские индексы Poetry/uv можно доверять только по точному разрешённому списку `trusted_indexes.pypi`; устаревшие манифесты предупреждают при каждом запуске, если `python_enforcement` не установлен в `poetry_only` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Cargo | Cargo.toml | Требуется `Cargo.lock` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Go | go.mod | `go.sum` требуется для внешних зависимостей; не требуется для стандартной библиотеки или полностью локальных `replace` | :white_check_mark: | :x: | :x: |
| Ruby | Gemfile | Требуется `Gemfile.lock` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PHP | composer.json | Требуется `composer.lock` | :white_check_mark: | :x: | :x: |
| JVM (Gradle) | build.gradle / build.gradle.kts | Требуется `gradle.lockfile` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| JVM (Maven) | pom.xml | только предупреждение: строгого контроля лок-файлов нет | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| .NET | *.csproj | Требуется `packages.lock.json` | :white_check_mark: | :x: | :x: |

Все экосистемы проходят проверки существования, сходства и каноничности. Метаданные и возрастной шлюз зависят от того, что предоставляет API реестра. Поддержка лок-файлов обеспечивает сканирование транзитивных зависимостей и точное разрешение версий в тех экосистемах, где существует надёжная модель проектного лок-файла.

## Быстрый старт```bash
# Install
cargo install sloppy-joe

# Check current project (auto-detects ecosystem)
sloppy-joe check

# Check with canonical enforcement and age gate
sloppy-joe check --config /etc/sloppy-joe/config.json

# Output as JSON for CI
sloppy-joe check --json

Коды выхода

КодЗначение
0Все проверки пройдены
1Обнаружены проблемы
2Ошибка выполнения

Конфигурация```json

{ "canonical": { "npm": { "lodash": ["underscore", "ramda", "lazy.js"], "dayjs": ["moment", "luxon"], "axios": ["request", "got", "node-fetch", "superagent"] }, "pypi": { "httpx": ["urllib3", "requests"], "ruff": ["flake8", "pylint"] } }, "internal": { "go": ["github.com/yourorg/"], "npm": ["@yourorg/"] }, "allowed": { "npm": ["some-vetted-external-pkg"] }, "similarity_exceptions": { "cargo": [ { "package": "serde_json", "candidate": "serde", "generator": "segment-overlap" } ] }, "metadata_exceptions": { "cargo": [ { "package": "colored", "check": "metadata/maintainer-change", "version": "2.2.0", "previous_publisher": "kurtlawrence", "current_publisher": "hwittenborn" } ] }, "min_version_age_hours": 72, "allow_legacy_npm_v1_lockfile": false, "python_enforcement": "prefer_poetry" }

root@kitploit:~
**`canonical`** — ключи — это одобренные пакеты; значения — отвергнутые альтернативы.

**`internal`** — пакеты вашей организации. Пропускать ВСЕ проверки. Они постоянно меняются.

**`allowed`** — проверенные внешние пакеты. Пропускать проверки на существование и сходство, но всё ещё подвержены проверке возраста версии.

**`similarity_exceptions`** — точные подавления package/candidate/generator для проверенных ложных срабатываний сходства. Используйте это, когда одно конкретное сходство неверно, но вы всё ещё хотите нормальные проверки для пакета.

**`metadata_exceptions`** — точные проверенные подавления метаданных. В настоящее время поддерживает только `metadata/maintainer-change` и требует точного совпадения package/version/previous-publisher/current-publisher.

Используйте `sloppy-joe check --review-exceptions`, когда нужно просмотреть блокировки смены мейнтейнера. Сканирование по-прежнему блокирует нормально, но в выводе для человека добавляется раздел `REVIEW EXCEPTIONS` с владельцами, URL репозитория и готовым к вставке фрагментом `metadata_exceptions`. `--json` включает те же данные в поле `review_candidates` верхнего уровня.

**`min_version_age_hours`** — блокировать любую версию, опубликованную менее этого количества часов назад. По умолчанию: 72 (3 дня). Установите 0, чтобы отключить. Внутренние пакеты освобождены.

**`allow_legacy_npm_v1_lockfile`** — разрешить lock-файлы npm `lockfileVersion: 1` от npm v5/v6 в режиме пониженного доверия. По умолчанию: `false`. Оставьте выключенным, если вы не застряли на устаревшем npm и не принимаете громкие предупреждения плюс сниженное покрытие доверенных транзитивных зависимостей npm.

**`python_enforcement`** — управляет политикой доверия Python. `prefer_poetry` (по умолчанию) доверяет проектам Poetry и uv, полностью доверяет требованиям pip-tools с хеш-локом только когда зафиксированный граф требований привязывает `--index-url` и любые значения `--extra-index-url` не из PyPy точно, в противном случае понижает pip-tools до пониженного доверия. Устаревшие манифесты, такие как `requirements*.txt` без хешей, `Pipfile`, `setup.cfg`, `setup.py` и `pyproject.toml` без Poetry/uv, предупреждают при каждом запуске. `poetry_only` блокирует такие не-Poetry Python-процессы и требует Poetry.

### Безопасность конфигурации

Конфигурация **никогда не читается из директории проекта**. AI-агент с доступом к оболочке мог бы перезаписать конфигурацию внутри репозитория, чтобы разрешить всё, что угодно.

Разрешение конфигурации:
1. `--config /path/to/config.json` — локальный файл (флаг CLI, наивысший приоритет)
2. `--config https://example.com/config.json` — загрузка по URL
3. `SLOPPY_JOE_CONFIG=...` — переменная окружения (путь к файлу или URL)
4. Нет конфигурации = только проверки существования + сходства + метаданных

Некорректные конфигурации **жёстко падают** с информативными сообщениями об ошибках — сломанная конфигурация никогда не возвращается молча к отсутствию защиты.

См. [CONFIG.md](https://github.com/brennhill/sloppy-joe/blob/HEAD/CONFIG.md) для полного справочника по формату, шаблонов интеграции CI и примеров.

Конфигурация начальной загрузки (bootstrap):```bash
sloppy-joe init --greenfield --ecosystem npm
sloppy-joe init --from-current
sloppy-joe init --from-current --register
sloppy-joe init --register

CI Integration

GitHub Actions

Самый быстрый способ добавить sloppy-joe в ваш CI-конвейер — загружает предварительно собранный бинарный файл из GitHub Releases (не требуется Rust toolchain):```yaml

.github/workflows/deps.yml

name: Dependency Check on: [push, pull_request]

jobs: sloppy-joe: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: brennhill/[email protected] with: config: https://raw.githubusercontent.com/yourorg/configs/main/sloppy-joe.json

root@kitploit:~
#### Входные данные действия

| Вход | Описание | По умолчанию |
|-------|-------------|---------|
| `config` | Путь к конфигурационному файлу или URL HTTPS | *(нет)* |
| `dir` | Каталог проекта для сканирования | `.` |
| `type` | Экосистема (`npm`, `pypi`, `cargo`, `go`, `ruby`, `php`, `jvm`, `dotnet`) | автоопределение |
| `deep` | Включить проверки сходства транзитивных зависимостей | `false` |
| `paranoid` | Включить мутации с переворотом битов | `false` |
| `args` | Дополнительные аргументы CLI | *(нет)* |
| `version` | Версия sloppy-joe для установки | `latest` |

#### Примеры```yaml
# Minimal — CI-oriented scan, auto-detect ecosystem, no config
- uses: brennhill/[email protected]

# With org config from a URL
- uses: brennhill/[email protected]
  with:
    config: https://raw.githubusercontent.com/yourorg/configs/main/sloppy-joe.json

# Deep scan with paranoid mode
- uses: brennhill/[email protected]
  with:
    config: ${{ secrets.SLOPPY_JOE_CONFIG }}
    deep: true
    paranoid: true

# Scan a subdirectory, pin to a specific version
- uses: brennhill/[email protected]
  with:
    dir: ./packages/api
    version: '1.1.0'

GitLab CI```yaml

dependency-guard: script: - cargo install sloppy-joe - sloppy-joe check --ci --config $SLOPPY_JOE_CONFIG

root@kitploit:~
### pre-commit

sloppy-joe работает с фреймворком [pre-commit](https://pre-commit.com).
Добавьте его в свой `.pre-commit-config.yaml`:```yaml
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/brennhill/sloppy-joe
    rev: v1.1.0
    hooks:
      - id: sloppy-joe

Хук запускает sloppy-joe check при каждом коммите (и опционально при пуше). Он автоматически определяет вашу экосистему по манифест-файлам. Передавайте дополнительные аргументы через args:```yaml - id: sloppy-joe args: [--config, "https://example.com/config.json"]

root@kitploit:~
Или используйте простой хук оболочки без фреймворка:```bash
#!/bin/sh
sloppy-joe check || exit 1

Архитектура

sloppy-joe использует генеративный подход на основе реестра для обнаружения сходства. Вместо сравнения каждой зависимости со статическим корпусом с помощью редакционного расстояния (что приводит к ложным срабатываниям), он генерирует специфические мутации имени каждой зависимости, запрашивает реестр для проверки существования мутации и помечает точные совпадения.``` Pipeline (in order):

  1. Canonical check — flag deps that violate org standards
  2. Similarity check — 8 mutation generators + scope squatting
  3. Metadata check — version age, new package, downloads, install scripts, dep explosion, maintainer change
  4. Existence check — flag packages that don't exist on the registry
  5. Malicious check — query OSV.dev for known vulnerabilities
root@kitploit:~
Поиск сходства выполняется в 4 этапа:
- **Этап 0: Сквоттинг области видимости** — локальная проверка, без сети. Сравнивает область/пространство имён с известными корректными областями через расстояние Левенштейна.
- **Этап 1: Внутриманифестная проверка** — локальная проверка. Помечает, когда две зависимости в одном манифесте являются мутациями друг друга.
- **Этап 2: Запрос к реестру** — генерирует мутации, пакетно опрашивает реестр на существование, кэширует результаты (TTL 7 дней).
- **Этап 3: Обогащение метаданными** — получает количество загрузок и даты публикации для совпадений, чтобы добавить доказательства в отчёты.

Каждый генератор мутаций помечает свой вывод, поэтому отображаемый тип проверки (например, `similarity/homoglyph`) детерминирован — генератор с наибольшей серьёзностью побеждает, когда несколько генераторов выдают одного и того же кандидата.

## Надёжность CI

sloppy-joe разработан для CI-конвейеров, где неприемлемы нестабильные сбои.

**Повтор с экспоненциальной задержкой.** Все HTTP-вызовы к реестру повторяются 3 раза с экспоненциальной задержкой (200ms, 400ms, 800ms) при временных сбоях (5xx, тайм-ауты, ошибки соединения). Одиночный сетевой сбой не приведёт к сбою вашей сборки.

**Блокировка при ошибках запроса.** Если запросы к реестру или OSV завершаются сбоем, sloppy-joe выдаёт блокирующую ошибку `registry-unreachable` вместо того, чтобы молча пропускать проверки. Сканирование больше не полагается на пороговые значения для каждой экосистемы или ограничения по размеру выборки перед блокировкой.

**Кэш сходства.** Результаты существования мутаций кэшируются на 7 дней. После первого сканирования большинство запросов обслуживаются из кэша без сетевых вызовов. Только новые зависимости инициируют запросы к реестру.

**Разрешение зависимостей с учётом lock-файла.** Когда присутствует и является надёжным поддерживаемый lock-файл (`package-lock.json`, `npm-shrinkwrap.json`, `Cargo.lock`, `Gemfile.lock`, `poetry.lock` для проектов Poetry, `uv.lock` для проектов uv, `composer.lock`, `gradle.lockfile`, `packages.lock.json`), sloppy-joe определяет точные версии из него, а не угадывает по диапазонам. Полностью хэш-заблокированные `requirements*.txt` также могут предоставлять точные закреплённые версии, и они становятся полностью доверенными, когда зафиксированный граф требований связывает собственный `--index-url` и точные разрешённые значения `--extra-index-url`.

## Тесты

Набор тестов охватывает проверки сходства, сигналы метаданных, поведение OSV, разбор и валидацию конфигурации, разрешение lock-файлов, политику предварительной проверки манифестов и lock-файлов, форматирование отчётов и логику повторных HTTP-запросов.```bash
cargo test

Основано на

  • Typomania — библиотека опечаток Rust Foundation, вдохновившая на генеративный подход мутаций (sloppy-joe реализует собственные генераторы, а не использует крейт напрямую)
  • strsim — расстояние Левенштейна, используется для обнаружения сквоттинга пространств имён
  • reqwest — асинхронный HTTP-клиент с повторами для запросов к реестру
  • OSV.dev — база данных известных уязвимостей для обнаружения вредоносных пакетов

Как sloppy-joe сравнивается

Где другие сильнее: Socket.dev выполняет глубокий анализ скриптов установки с поведенческим обнаружением, что выходит далеко за рамки флагового подхода sloppy-joe. cargo-deny обладает лучшим в своём классе контролем соответствия лицензиям, но это намеренно выходит за рамки sloppy-joe, потому что лицензионная политика — это проблема соответствия, а не средство безопасности зависимостей. npm audit и pip-audit — это варианты без установки для сканирования уязвимостей в одной экосистеме.

Чем sloppy-joe отличается: Это единственный инструмент, который проверяет, существуют ли пакеты в реестрах (выявляя галлюцинации ИИ), запускает 11 генераторов опечаток с почти нулевым уровнем ложных срабатываний, обеспечивает канонический выбор пакетов и хранит свою конфигурацию вне репозитория, чтобы агенты ИИ не могли ослабить собственные проверки.

Лицензия

Apache 2.0

Скачать инструмент
sloppy-joe check
--ci
--full
ЭкосистемаОбязательный манифестДоверенный lockfile / состояние проекта
JavaScript / npmpackage.jsonpackage-lock.json или npm-shrinkwrap.json; устаревший npm v1 блокируется по умолчанию
JavaScript / pnpmpackage.jsonpnpm-lock.yaml
JavaScript / Yarnpackage.jsonyarn.lock
JavaScript / Bunpackage.jsonbun.lock
Pythonpyproject.toml, requirements*.txt, Pipfile, setup.cfg или setup.pyдоверенный путь Poetry использует poetry.lock, доверенный путь uv использует uv.lock, а полностью хеш-блокированный pip-tools доверяется только тогда, когда зафиксированный граф требований (requirements graph) точно привязывает значения --index-url и любые --extra-index-url; видимые в репозитории индексы Python могут быть добавлены в белый список через trusted_indexes.pypi; доверенные режимы Python оценивают один выбранный профиль установки за раз (runtime по умолчанию, явные группы/extras/платформа/архитектура/версия через CLI); устаревшие манифесты допускаются с предупреждениями по умолчанию
RustCargo.tomlCargo.lock
Gogo.modgo.sum требуется для внешних зависимостей
RubyGemfileGemfile.lock
PHP / Composercomposer.jsoncomposer.lock
JVM / Gradlebuild.gradle или build.gradle.ktsgradle.lockfile
JVM / Mavenpom.xmlтолько предупреждение: доверенного локального lockfile проекта пока нет
.NET / NuGet.csprojpackages.lock.json
sloppy-joeSocket.devGuardDogPhantom Guardantislopsquat
Проверка существования✅✅❌✅✅
Похожесть / тайпсквоттинг✅✅✅✅❌
Обнаружение гомоглифов✅❌❌❌❌
Захват области видимости✅❌❌❌❌
Каноническое принуждение✅❌❌❌❌
Шлюз по возрасту версии✅❌❌❌❌
Усилитель скриптов установки✅✅❌❌❌
Взрыв зависимостей✅❌❌❌❌
Смена мейнтейнера✅✅❌❌❌
Проверка уязвимостей через OSV✅✅❌❌❌
Безопасность конфигурации (вне репозитория)✅N/A❌❌❌
Внутренние + разрешённые списки✅❌❌❌❌
npm✅✅✅✅❌
PyPI✅✅✅✅✅
Cargo✅✅❌✅❌
Go✅✅✅❌❌
Ruby✅✅✅❌❌
PHP✅🔶❌❌❌
JVM (Gradle/Maven)✅✅❌❌❌
.NET (NuGet)✅✅❌❌❌
Один бинарник✅❌❌❌❌
Открытый исходный кодApache 2.0КоммерческийApache 2.0MITOSS
ЯзыкRustSaaSPythonPythonPython
false
--metrics-port
9092
--silent-an
false
--passive
false
--env-vars
false
--show-var-dump
false
--code
false
--force-http2
false
--disable-stdin
false
--client-cert
pem
crt
p12
| | `--client-key` | No | Настроить клиентский ключ для аутентификации с целевым объектом сканирования. Поддерживаются форматы `pem`, `crt`, `p12`. |
--client-ca
pem
crt
p12
| | `--client-asn` | No | Настроить аутентификацию с использованием определённого ASN для клиентского сертификата. |
--ztls
false
--ztls-fallback
false
--ztls-sni
Featuresloppy-joeSocket.devcargo-denypip-auditnpm audit
Обнаружение галлюцинированных пакетов✅❌❌❌❌
Обнаружение опечаток✅ 11 генераторовЧастично❌❌❌
Принуждение к каноническим именам✅❌❌❌❌
Сканирование известных уязвимостей✅ через OSV✅✅✅✅
Анализ скриптов установкиБазовый (флаг + без репозитория)✅ Глубокий анализ❌❌❌
Соответствие лицензиямВне области: соблюдение, не безопасность✅✅ ОтличноВне области: соблюдение, не безопасностьВне области: соблюдение, не безопасность
Мультиэкосистема8 экосистемnpm, PyPI, Go, Ruby, Java, .NETТолько RustТолько PythonТолько npm
Безопасность ИИ-агентов (конфигурация вне репозитория)✅❌❌❌❌
Удобство для офлайн/CI✅ Работает вездеТребует платформу Socket✅✅✅
Бесплатно / с открытым исходным кодомApache 2.0Бесплатный уровень + платныйApache 2.0Apache 2.0Встроенный