Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
sloppy-joe — Protège contre les attaques de supply-chain, de slopsquatting et de typosquatting provenant des dépendances et du code. | Kitploit
Outils/GitHubGitHub/brennhill/sloppy-joe
Analyse StatiqueScanners de VulnérabilitésAnalyse de CodeDevSecOpsDétection de SecretsRenseignement sur les MenacesSécurité de la Chaîne LogistiqueApprentissage et Éducation
GitHubbrennhill/sloppy-joe

sloppy-joe

Protège contre les attaques de supply-chain, de slopsquatting et de typosquatting provenant des dépendances et du code.

Voir le dépôt
3213il y a 4 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

sloppy-joe

Attraper les dépendances hallucinées, typosquattées et non canoniques
avant qu'elles n'atteignent la production.

cargo install sloppy-joe


L'attaque à la chaîne d'approvisionnement LiteLLM (mars 2026) a compromis un paquet avec 97 millions de téléchargements mensuels. Les attaquants ont volé des identifiants de publication, poussé des versions malveillantes qui ont récolté des clés SSH, des identifiants cloud et des secrets K8s. La barrière d'âge de version par défaut de 72 heures de sloppy-joe aurait bloqué les deux versions empoisonnées — elles ont été découvertes en quelques heures, bien avant que la barrière ne s'ouvre. Si vous exécutez sloppy-joe check dans CI, cette attaque échoue. Analyse complète

Les générateurs de code IA hallucinent des noms de paquets ~20% du temps. Les attaquants enregistrent ces noms et attendent. sloppy-joe les détecte dans CI avant que ou ne s'exécutent.

npm install
pip install

Comment utiliser```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

Modes d’analyse :

  • sloppy-joe check exécute le garde-fou local rapide. Il applique toujours l’analyse du manifeste, la vérification du fichier de verrouillage/synchronisation, la provenance et la politique des sources non prises en charge. Si l’état des dépendances ou de la politique a changé, ou si la dernière analyse complète réussie date de plus de 24 heures, il recommande sloppy-joe check --full.
  • sloppy-joe check --full exécute l’analyse en ligne stricte et rafraîchit l’état enregistré de la dernière analyse complète réussie.
  • sloppy-joe check --ci exécute la même couverture stricte que --full, avec une orientation CI.
  • Pour Python, sloppy-joe check évalue le profil runtime par défaut. Si des dépendances limitées existent, il prévient et vous demande de passer explicitement les drapeaux --python-groups, --python-extras, --python-platform et/ou --python-version pour la parité CI/construction.
  • La sortie lisible par l’humain de sloppy-joe check vous rappelle toujours d’utiliser --ci ou --full pour la CI et le passage en production.

Codes de sortie : 0 = aucun problème bloquant trouvé dans le mode sélectionné, 1 = problèmes bloquants trouvés, 2 = erreur d’exécution.

Pris en charge : JavaScript (npm, pnpm, Yarn, Bun), Python, Rust, Go, Ruby, PHP, JVM (Gradle/Maven) et .NET — détectés automatiquement à partir des fichiers manifeste.

Guides par écosystème : voir docs/ecosystems/README.md pour le modèle de confiance actuel, les fonctionnalités prises en charge et les limites de fermeture en cas d’échec pour chaque écosystème.

  • JavaScript
  • Python
  • Rust
  • Go
  • Ruby
  • PHP / Composer
  • JVM
  • .NET / NuGet
ÉcosystèmeManifeste requisFichier de verrouillage / état du projet de confiance
JavaScript / npmpackage.jsonpackage-lock.json ou npm-shrinkwrap.json ; npm v1 hérité bloqué par défaut
JavaScript / pnpmpackage.jsonpnpm-lock.yaml
JavaScript / Yarnpackage.jsonyarn.lock
JavaScript / Bunpackage.jsonbun.lock
Pythonpyproject.toml, requirements*.txt, Pipfile, setup.cfg ou setup.pyle chemin Poetry de confiance utilise poetry.lock, le chemin uv de confiance utilise uv.lock, et pip-tools entièrement verrouillé par hachage n’est digne de confiance que lorsque le graphe des exigences commité lie exactement les valeurs --index-url et les éventuels --extra-index-url ; les index Python visibles dans le dépôt peuvent être autorisés via trusted_indexes.pypi ; les modes Python de confiance évaluent un profil d’installation sélectionné à la fois (runtime par défaut, groupes/extras/plateforme/architecture/version explicites via CLI) ; les manifestes hérités sont autorisés avec avertissements par défaut
RustCargo.tomlCargo.lock
Gogo.modgo.sum requis pour les dépendances externes
RubyGemfileGemfile.lock
PHP / Composercomposer.jsoncomposer.lock
JVM / Gradlebuild.gradle ou build.gradle.ktsgradle.lockfile
JVM / Mavenpom.xmlavertissement uniquement : aucun chemin de fichier de verrouillage local de confiance pour l’instant

Sources de configuration : chemin de fichier local, URL HTTPS, ou variable d’environnement SLOPPY_JOE_CONFIG. La configuration n’est jamais lue depuis le répertoire du projet (voir CONFIG.md pour la raison).

Intégration : utilisez le mode d’amorçage correspondant au dépôt :

  • sloppy-joe init --greenfield --ecosystem <eco> affiche une politique de démarrage spécifique à l’écosystème pour les nouveaux projets. Aujourd’hui, les presets greenfield sont implémentés pour npm, pypi et cargo ; les autres écosystèmes échouent avec une erreur « pas encore pris en charge ». Ajoutez --register pour l’écrire en dehors du dépôt et l’enregistrer en toute sécurité.
  • sloppy-joe init --from-current inspecte le dépôt actuel et affiche des suggestions d’amorçage uniquement pour révision. Aujourd’hui, --from-current n’est implémenté que pour les dépôts dont le code propriétaire est npm et/ou cargo ; les autres écosystèmes échouent de manière fermée avec une erreur « pas encore implémenté ». Ajoutez --register pour écrire et enregistrer la configuration générée.
  • sloppy-joe init sans mode affiche un modèle manuel neutre.

Pourquoi sloppy-joe ?

Binaire unique. 8 écosystèmes. 16 types d’attaques. Zéro faux positif sur les vérifications génératives. Configuration que les agents IA ne peuvent pas falsifier.

La plupart des outils de sécurité des dépendances vérifient une ou deux choses — l’existence, ou la distance d’édition. sloppy-joe vérifie 16 vecteurs d’attaque en un seul passage : paquets hallucinés, 10 types de typosquatting (homoglyphes, usurpation de portée, caractères répétés, confusion de séparateur, réorganisation de mots, permutations adjacentes, caractères omis, formes confondues, variantes de casse, suffixes de version), application canonique, contrôle de l’âge de la version, amplification des scripts d’installation, explosion des dépendances, changements de mainteneur et vulnérabilités connues via OSV.dev.

Il s’exécute en un seul binaire Rust sans dépendances d’exécution. Il prend en charge les 8 principaux écosystèmes de paquets. Et sa configuration est conçue pour la sécurité : jamais lue depuis le répertoire du projet, chargeable depuis une URL pour la CI, avec des messages d’erreur clairs en cas de problème.

sloppy-joeSocket.devGuardDogPhantom Guardantislopsquat
Vérification d’existence✅✅❌✅✅
Similitude / typosquatting✅✅✅✅❌
Détection d’homoglyphes✅❌❌❌❌
Usurpation de portée✅❌❌❌❌
Application canonique✅❌❌❌❌
Contrôle de l’âge de la version✅❌❌❌❌
Amplificateur de script d’installation✅✅❌❌❌
Explosion des dépendances✅❌❌❌❌
Changement de mainteneur✅✅❌❌❌
Vérification des vulnérabilités OSV✅✅❌❌❌
Sécurité de la configuration (hors dépôt)✅N/A❌❌

🔶 = bêta/expérimental


Comment chaque attaque fonctionne (et comment sloppy-joe la bloque)

1. Paquets hallucinés

L’attaque : L’IA génère import ai_json_helper. Le paquet n’existe pas. Un attaquant enregistre ai-json-helper sur PyPI avec un malware. La prochaine fois que quelqu’un exécute pip install, il obtient le paquet malveillant.

Comment sloppy-joe la bloque : La vérification d’existence interroge l’API PyPI et obtient un 404. Construction bloquée.``` 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. Typosquattage (vérifications génératives + fallback par distance d'édition)

**L'attaque :** Un attaquant enregistre `expresz` sur npm — à un caractère près de `express`. L'IA le génère, ou un développeur le tape mal. Le paquet existe, réussit le contrôle d'existence, et installe un logiciel malveillant.

**Comment sloppy-joe le bloque :** sloppy-joe exécute 10 vérifications génératives avant de recourir à la distance d'édition. Chaque vérification générative produit une mutation spécifique du nom de la dépendance (échanger des caractères, compresser les répétitions, supprimer les suffixes, réordonner les mots, normaliser les séparateurs, remplacer les homoglyphes, vérifier les scopes) et teste une correspondance exacte avec les paquets populaires connus. Cette approche, inspirée de la bibliothèque [Typomania de la Rust Foundation](https://github.com/rustfoundation/typomania), présente un taux de faux positifs quasi nul car elle ne se déclenche que sur des correspondances exactes après mutation.

La distance d'édition de Levenshtein s'exécute en dernier comme filet de sécurité pour les mutations inédites qu'aucune vérification spécifique n'a anticipées. Ensemble, elles couvrent à la fois les schémas d'attaque connus (précisément) et inconnus (largement).```
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. Caractères répétés

L'attaque : expresss (s supplémentaire) ou reeact (e supplémentaire). Ce sont des motifs courants d'hallucination par IA — le modèle génère des noms d'apparence plausible avec des caractères répétés.

Comment sloppy-joe le bloque : La vérification des caractères répétés supprime un doublon à la fois et vérifie si le résultat correspond à un paquet connu. expresss → suppression d'un s → express → correspondance.``` ERROR expresss [similarity/repeated-chars] 'expresss' matches 'express' after removing a repeated character. Fix: Use 'express' — remove the repeated characters.

root@kitploit:~
### 4. Confusion de séparateur

**L'attaque:** `python-dateutil` vs `python_dateutil` vs `pythondateutil`. Sur certains registres, ce sont des paquets différents. Un attaquant enregistre la variante.

**Comment sloppy-joe le bloque:** Normalise tous les séparateurs (`-`, `_`, `.`) avant la comparaison. Si la forme normalisée correspond à un paquet connu, elle est signalée.```
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. Réorganisation des mots

L'attaque : parse-json vs json-parse. La distance de Levenshtein est de 8 — invisible aux vérifications de distance d'édition. Mais un attaquant peut enregistrer le nom réorganisé.

Comment sloppy-joe le bloque : Divise sur les séparateurs, génère toutes les permutations des segments, et vérifie chacune par rapport au corpus. parse-json → permutation → json-parse → correspondance.``` 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. Échanges de caractères adjacents

**L'attaque :** `reqeust` au lieu de `request`. Deux caractères adjacents transposés — une faute de frappe courante que les attaquants exploitent.

**Comment sloppy-joe le bloque :** Génère toutes les variantes de permutation de caractères adjacents du nom de la dépendance et vérifie chacune par rapport au corpus.```
ERROR reqeusts [similarity/char-swap]
      'reqeusts' matches 'requests' with two adjacent characters swapped.
 Fix: Use 'requests' — two characters are transposed.

7. Caractères omis

L'attaque : reqests (manque u) au lieu de requests. L'IA supprime un caractère et le résultat est un nom d'apparence valide.

Comment sloppy-joe le bloque : Insère chaque caractère a-z à chaque position dans le nom et vérifie si un résultat correspond à un paquet connu. reqests + u à la position 3 → requests → correspondance.``` ERROR reqests [similarity/omitted-char] 'reqests' matches 'requests' with one character inserted. Fix: Use 'requests' — a character appears to be missing.

root@kitploit:~
### 8. Homoglyphes (similitudes visuelles)

**L'attaque :** `rеquests` avec un `е` cyrillique (U+0435) au lieu du `e` latin (U+0065). Visuellement identique. Le nom du paquet ressemble exactement à `requests` mais renvoie vers un paquet malveillant différent.

**Comment sloppy-joe le bloque :** Remplace 17 caractères homoglyphes connus (cyrilliques, pleine largeur, variantes script) par leurs équivalents latins et vérifie si le résultat correspond à un paquet connu.```
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. Formes confuses d'écosystème

L'attaque : py-utils vs python-utils. Sur PyPI, ce sont des packages différents. L'IA génère l'un quand vous vouliez l'autre. De même, github.com vs gitlab.com dans les modules Go.

Comment sloppy-joe le bloque : Applique des règles de substitution spécifiques à l'écosystème (py↔python pour PyPI, github↔gitlab pour Go) et vérifie si une variante correspond à un package connu.``` ERROR py-flask [similarity/confused-form] 'py-flask' is a confused form of 'flask'. Fix: Use the canonical name 'flask'.

root@kitploit:~
### 10. Attaques par variante de casse (registres sensibles à la casse)

**L'attaque :** Sur Go, Maven et Ruby, `Rails` et `rails` sont des packages différents. Un attaquant enregistre la variante en majuscule.

**Comment sloppy-joe le bloque :** Sur les registres sensibles à la casse, toute variante de casse d'un package connu est signalée comme une erreur. Sur les registres insensibles à la casse (npm, PyPI, Cargo, NuGet, PHP), les variantes de casse sont sûres et ignorées.```
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. Squattage par suffixe de version

L'attaque : requests2 ou lodash-4. L'IA ajoute un numéro de version au nom du paquet au lieu de spécifier correctement la version.

Comment sloppy-joe le bloque : Supprime les chiffres et séparateurs en fin de chaîne et vérifie si le nom de base correspond à un paquet connu.``` 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. Usurpation de scope (npm, PHP, Go, JVM)

**L'attaque :** Un attaquant enregistre `@typos/lodash` sur npm — un caractère de différence avec `@types/lodash`. Ou `larvael/framework` sur Packagist — deux caractères de `laravel/framework`. Ou `github.com/gooogle/protobuf` sur Go — un `o` supplémentaire. Le scope semble légitime à première vue. Le paquet résout. Le malware s'installe.

C'est rare mais plausible — et « rare mais plausible » est exactement ce pour quoi sloppy-joe existe. L'incident `ua-parser-js` en 2021 était lié au scope. Si cela peut arriver à un paquet avec des millions de téléchargements hebdomadaires, cela peut arriver au vôtre.

**Comment sloppy-joe le bloque :** Extrait le scope/namespace du nom de dépendance et le compare à une liste de scopes connus comme fiables en utilisant la distance d'édition. Fonctionne sur npm (`@scope`), PHP (`vendor/`), Go (`github.com/org`), et 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.

Comme vous pouvez le voir, nous devons les placer toutes dans un répertoire qui peut être passé en argument à l'outil ou placé dans Docker Home en cas d'exécution Docker.``` 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. Paquets non canoniques (pas une attaque — une barrière de cohérence)

**L'attaque :** Pas une attaque — un problème de cohérence. L'IA choisit `moment` parce qu'il était populaire dans les données d'entraînement, mais votre équipe utilise `dayjs`. Des équipes différentes utilisant des paquets différents pour la même tâche créent une dette de maintenance et un gonflement des dépendances.

**Comment sloppy-joe le bloque :** Votre configuration associe chaque paquet canonique à ses alternatives rejetées. Si une dépendance correspond à une alternative, la construction échoue.```
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. Versions trop récentes (bombe à retardement dans la chaîne d'approvisionnement)

L'attaque : Un attaquant compromet le compte d'un mainteneur de paquet (ou un mainteneur devient malveillant) et publie une version de correctif malveillante. Cela ressemble à une mise à jour normale. Si votre CI l'installe immédiatement, vous êtes compromis avant que quiconque ne s'en aperçoive.

Comment sloppy-joe le bloque : La barrière d'âge des versions bloque toute dépendance dont la version a été publiée il y a moins de min_version_age_hours heures (par défaut : 72 heures). Cela donne à la communauté, à Socket.dev et aux autres scanners le temps de signaler les versions malveillantes.``` 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. Paquets flambant neufs

**L'attaque :** Un paquet créé hier avec 3 téléchargements et dont le nom ressemble à celui d'un paquet populaire. Forte probabilité qu'il s'agisse d'un typosquatting ou d'un espace réservé pour une future attaque.

**Comment sloppy-joe le bloque :** Signale tout paquet créé il y a moins de 30 jours.```
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. Paquets à faible nombre de téléchargements

L'attaque : Un paquet avec 12 téléchargements qui se trouve à un caractère près de requests. Presque certainement un typosquat.

Comment sloppy-joe le bloque : Signale les paquets avec moins de 100 téléchargements (là où le registre fournit les données de téléchargement — actuellement 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:~
---

## Écosystèmes pris en charge

| Écosystème | Manifeste | Politique de verrouillage | Existence | Métadonnées | Filtrage par âge |
|-----------|----------|-----------------|:---------:|:--------:|:--------:|
| npm | package.json | `package-lock.json` ou `npm-shrinkwrap.json` requis | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PyPI | `pyproject.toml`, `requirements*.txt`, `Pipfile`, `setup.cfg`, `setup.py` | Poetry est approuvé avec `poetry.lock`, uv est approuvé avec `uv.lock`, pip-tools à verrouillage complet par hachage n'est approuvé que lorsque le graphe de dépendances commité lie `--index-url` et des valeurs `--extra-index-url` explicitement autorisées, et les index personnalisés Poetry/uv visibles dans le dépôt ne peuvent être approuvés que par la liste blanche exacte `trusted_indexes.pypi` ; les manifestes hérités émettent un avertissement à chaque exécution sauf si `python_enforcement` est `poetry_only` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Cargo | Cargo.toml | `Cargo.lock` requis | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Go | go.mod | `go.sum` requis pour les dépendances externes ; non requis pour la stdlib seule ou pour les `replace` tous locaux | :white_check_mark: | :x: | :x: |
| Ruby | Gemfile | `Gemfile.lock` requis | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PHP | composer.json | `composer.lock` requis | :white_check_mark: | :x: | :x: |
| JVM (Gradle) | build.gradle / build.gradle.kts | `gradle.lockfile` requis | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| JVM (Maven) | pom.xml | avertissement uniquement : pas d'application stricte du fichier de verrouillage | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| .NET | *.csproj | `packages.lock.json` requis | :white_check_mark: | :x: | :x: |

Tous les écosystèmes bénéficient des vérifications d'existence, de similarité et de canonicité. Les métadonnées et le filtrage par âge dépendent de ce que l'API du registre expose. Le support des fichiers de verrouillage permet l'analyse des dépendances transitives et la résolution exacte des versions lorsque l'écosystème fournit un modèle de fichier de verrouillage local au projet digne de confiance.

## Démarrage rapide```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

Codes de sortie

CodeSignification
0Tous les contrôles réussis
1Problèmes trouvés
2Erreur d'exécution

Configuration```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`** — les clés sont les paquets approuvés ; les valeurs sont les alternatives rejetées.

**`internal`** — les paquets de votre organisation. Ignorer TOUS les contrôles. Ceux-ci changent constamment.

**`allowed`** — paquets externes vérifiés. Ignorer l'existence + la similarité, mais toujours soumis à la barrière d'âge de version.

**`similarity_exceptions`** — suppressions exactes de paquet/candidat/générateur pour les faux positifs de similarité examinés. Utilisez ceci lorsque un bord de similarité spécifique est incorrect mais que vous souhaitez toujours les contrôles normaux sur le paquet.

**`metadata_exceptions`** — suppressions exactes de métadonnées examinées. Actuellement, cela ne prend en charge que `metadata/maintainer-change`, et nécessite une correspondance exacte paquet/version/éditeur-précédent/éditeur-actuel.

Utilisez `sloppy-joe check --review-exceptions` lorsque vous devez examiner les bloqueurs de changement de mainteneur. L'analyse bloque toujours normalement, mais la sortie humaine ajoute une section `REVIEW EXCEPTIONS` avec les propriétaires, l'URL du dépôt et un extrait prêt à coller `metadata_exceptions`. `--json` inclut les mêmes données dans un champ de premier niveau `review_candidates`.

**`min_version_age_hours`** — bloquer toute version publiée il y a moins de ce nombre d'heures. Défaut : 72 (3 jours). Mettre à 0 pour désactiver. Les paquets internes sont exemptés.

**`allow_legacy_npm_v1_lockfile`** — autoriser les lockfiles npm `lockfileVersion: 1` de npm v5/v6 en mode confiance réduite. Défaut : `false`. Gardez-le désactivé sauf si vous êtes intentionnellement bloqué sur un npm hérité et acceptez des avertissements bruyants plus une couverture transitive npm de confiance réduite.

**`python_enforcement`** — contrôle la politique de confiance Python. `prefer_poetry` (défaut) fait confiance aux projets Poetry et uv, fait confiance aux exigences pip-tools entièrement verrouillées par hachage uniquement lorsque le graphe des exigences validé lie exactement `--index-url` et toutes les valeurs non-PyPI `--extra-index-url`, et sinon rétrograde pip-tools en confiance réduite. Les manifestes hérités comme `requirements*.txt` non hachés, `Pipfile`, `setup.cfg`, `setup.py` et `pyproject.toml` non-Poetry/non-uv avertissent à chaque exécution. `poetry_only` bloque ces workflows Python non-Poetry et exige Poetry.

### Config Security

La configuration n'est **jamais lue depuis le répertoire du projet**. Un agent IA avec accès shell pourrait réécrire une configuration dans le dépôt pour mettre en liste blanche tout ce qu'il veut.

Résolution de la configuration :
1. `--config /path/to/config.json` — fichier local (drapeau CLI, priorité la plus élevée)
2. `--config https://example.com/config.json` — récupérer depuis une URL
3. `SLOPPY_JOE_CONFIG=...` — variable d'environnement (chemin de fichier ou URL)
4. Pas de configuration = contrôles d'existence + similarité + métadonnées uniquement

Les configurations malformées **échouent durement** avec des messages d'erreur exploitables — une configuration cassée ne revient jamais silencieusement à aucune protection.

Voir [CONFIG.md](https://github.com/brennhill/sloppy-joe/blob/main/CONFIG.md) pour la référence complète du format, les modèles d'intégration CI et des exemples.

Configuration d'amorçage :```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

Le moyen le plus rapide d'ajouter sloppy-joe à votre pipeline CI — télécharge un binaire précompilé depuis GitHub Releases (aucun outillage Rust requis) :```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:~
#### Entrées d'action

| Entrée | Description | Défaut |
|--------|-------------|--------|
| `config` | Chemin du fichier de configuration ou URL HTTPS | *(aucun)* |
| `dir` | Répertoire du projet à analyser | `.` |
| `type` | Écosystème (`npm`, `pypi`, `cargo`, `go`, `ruby`, `php`, `jvm`, `dotnet`) | auto-détection |
| `deep` | Activer les vérifications de similarité des dépendances transitives | `false` |
| `paranoid` | Activer les mutations bitflip | `false` |
| `args` | Arguments CLI supplémentaires | *(aucun)* |
| `version` | Version de sloppy-joe à installer | `latest` |

#### Exemples```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 fonctionne avec le framework [pre-commit](https://pre-commit.com).
Ajoutez-le à votre `.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

Le hook exécute sloppy-joe check à chaque commit (et optionnellement lors du push). Il détecte automatiquement votre écosystème à partir des fichiers manifeste. Passez des arguments supplémentaires via args :```yaml - id: sloppy-joe args: [--config, "https://example.com/config.json"]

root@kitploit:~
Ou utilisez un simple shell hook sans le framework :```bash
#!/bin/sh
sloppy-joe check || exit 1

Architecture

sloppy-joe utilise une approche générative basée sur le registre pour la détection de similarité. Au lieu de comparer chaque dépendance à un corpus statique avec une distance d'édition (qui produit des faux positifs), il génère des mutations spécifiques de chaque nom de dépendance, interroge le registre pour vérifier si la mutation existe, et signale les correspondances exactes.``` 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:~
Similarité exécute 4 phases :
- **Phase 0 : Squatting de scope** — vérification locale, pas de réseau. Compare le scope/namespace avec les scopes connus via la distance de Levenshtein.
- **Phase 1 : Intra-manifeste** — vérification locale. Signale lorsque deux dépendances dans le même manifeste sont des mutations l'une de l'autre.
- **Phase 2 : Requête au registre** — génère des mutations, interroge le registre par lots pour l'existence, met en cache les résultats (TTL de 7 jours).
- **Phase 3 : Enrichissement des métadonnées** — récupère les compteurs de téléchargements et les dates de publication pour les correspondances afin d'ajouter des preuves aux rapports.

Chaque générateur de mutation étiquette sa sortie, de sorte que le type de vérification signalé (par exemple, `similarity/homoglyph`) est déterministe — le générateur de plus haute sévérité l'emporte lorsque plusieurs générateurs produisent le même candidat.

## Fiabilité CI

sloppy-joe est conçu pour les pipelines CI où les échecs intermittents sont inacceptables.

**Nouvelle tentative avec backoff.** Tous les appels HTTP au registre sont retentés 3 fois avec un backoff exponentiel (200ms, 400ms, 800ms) en cas d'échecs transitoires (5xx, timeouts, erreurs de connexion). Un simple incident réseau ne fera pas échouer votre build.

**Échec fermé en cas d'erreurs de requête.** Si les requêtes au registre ou à OSV échouent, sloppy-joe émet une erreur bloquante `registry-unreachable` au lieu d'ignorer silencieusement les vérifications. L'analyse ne repose plus sur des seuils par écosystème ou des limites de taille d'échantillon avant de bloquer.

**Cache de similarité.** Les résultats d'existence des mutations sont mis en cache pendant 7 jours. Après la première analyse, la plupart des requêtes sont servies depuis le cache sans aucun appel réseau. Seules les nouvelles dépendances déclenchent des requêtes au registre.

**Résolution consciente des lockfiles.** Lorsqu'un lockfile pris en charge et fiable est présent (`package-lock.json`, `npm-shrinkwrap.json`, `Cargo.lock`, `Gemfile.lock`, `poetry.lock` pour les projets Poetry, `uv.lock` pour les projets uv, `composer.lock`, `gradle.lockfile`, `packages.lock.json`), sloppy-joe résout les versions exactes à partir de celui-ci au lieu de les déduire des plages. Les `requirements*.txt` entièrement verrouillés par hachage peuvent également fournir des versions exactes épinglées, et ils deviennent totalement fiables lorsque le graphe de dépendances commité lie son propre `--index-url` et les valeurs exactes de `--extra-index-url` autorisées.

## Tests

La suite de tests couvre les vérifications de similarité, les signaux de métadonnées, le comportement OSV, l'analyse et la validation de la configuration, la résolution des lockfiles, la politique de pré-vérification des manifestes et lockfiles, le formatage des rapports et la logique de nouvelle tentative HTTP.```bash
cargo test

Développé avec

  • Typomania — bibliothèque de typosquatting de la Fondation Rust, qui a inspiré l'approche de mutation générative (sloppy-joe implémente ses propres générateurs plutôt que d'utiliser directement la crate)
  • strsim — distance de Levenshtein, utilisée pour la détection de squatting de scope
  • reqwest — client HTTP asynchrone avec tentatives pour les requêtes de registre
  • OSV.dev — base de données de vulnérabilités connues pour la détection de paquets malveillants

Comparaison de sloppy-joe avec d'autres outils

Fonctionnalitésloppy-joeSocket.devcargo-denypip-auditnpm audit
Détection de paquets hallucinés✅❌❌❌❌
Détection de typosquatting✅ 11 générateursPartiel❌❌❌
Respect du nom canonique✅❌❌❌❌
Analyse des vulnérabilités connues✅ via OSV✅✅✅✅
Analyse de script d'installationBasique (indicateur + pas de dépôt)✅ Analyse approfondie❌❌❌
Conformité des licencesHS : conformité, pas sécurité✅✅ ExcellentHS : conformité, pas sécuritéHS : conformité, pas sécurité
Multi-écosystèmes8 écosystèmesnpm, PyPI, Go, Ruby, Java, .NETRust uniquementPython uniquementnpm uniquement
Sécurité des agents IA (configuration hors dépôt)✅❌❌❌❌
Hors ligne / adapté à l'IC✅ Fonctionne partoutNécessite la plateforme Socket✅✅✅
Gratuit / open sourceApache 2.0Niveau gratuit + payantApache 2.0

Là où les autres sont plus forts : Socket.dev effectue une analyse approfondie des scripts d'installation avec une détection comportementale qui dépasse de loin l'approche basée sur les indicateurs de sloppy-joe. cargo-deny offre la meilleure vérification de conformité des licences, mais cela est intentionnellement hors du champ de sloppy-joe car la politique de licence est un problème de conformité plutôt qu'un contrôle de sécurité des dépendances. npm audit et pip-audit sont des options sans installation pour l'analyse de vulnérabilités mono-écosystème.

Ce qui différencie sloppy-joe : C'est le seul outil qui vérifie que les paquets existent réellement sur les registres (ce qui permet de détecter les hallucinations d'IA), qui exécute 11 générateurs de typosquatting avec des faux positifs quasi nuls, qui impose des choix de paquets canoniques et qui conserve sa configuration en dehors du dépôt afin que les agents IA ne puissent pas affaiblir leurs propres vérifications.

Licence

Apache 2.0

Télécharger l’outil
.NET / NuGet.csprojpackages.lock.json
❌
Listes internes et autorisées✅❌❌❌❌
npm✅✅✅✅❌
PyPI✅✅✅✅✅
Cargo✅✅❌✅❌
Go✅✅✅❌❌
Ruby✅✅✅❌❌
PHP✅🔶❌❌❌
JVM (Gradle/Maven)✅✅❌❌❌
.NET (NuGet)✅✅❌❌❌
Binaire unique✅❌❌❌❌
Open sourceApache 2.0CommercialApache 2.0MITOSS
LangageRustSaaSPythonPythonPython
Apache 2.0
Intégré