
Schützt vor Lieferketten-, Slopsquatting- und Typosquatting-Angriffen von Abhängigkeiten und Code.
cargo install sloppy-joe
Der LiteLLM-Lieferkettenangriff (März 2026) gefährdete ein Paket mit 97 Millionen monatlichen Downloads. Angreifer stahlen Veröffentlichungsanmeldeinformationen, veröffentlichten bösartige Versionen, die SSH-Schlüssel, Cloud-Anmeldeinformationen und K8s-Geheimnisse abschöpften. sloppy-joes standardmäßiges 72-Stunden-Versionsaltersgate hätte beide vergifteten Versionen blockiert – sie wurden innerhalb von Stunden entdeckt, lange bevor das Gate geöffnet worden wäre. Wenn Sie
sloppy-joe checkin CI ausführen, scheitert dieser Angriff. Vollständige Analyse
KI-Codegeneratoren halluzinieren Paketnamen ~20% der Zeit. Angreifer registrieren diese Namen und warten. sloppy-joe fängt sie in CI ab, bevor npm install oder pip install ausgeführt wird.
cargo install sloppy-joe
sloppy-joe check
sloppy-joe check --full
sloppy-joe check --ci
sloppy-joe check --dir ./my-project
sloppy-joe check --type npm
sloppy-joe check --python-groups dev,test --python-version 3.12 sloppy-joe check --python-extras docs --python-platform linux --python-version 3.12
sloppy-joe check --config /etc/sloppy-joe/config.json
sloppy-joe check --config https://raw.githubusercontent.com/yourorg/security-configs/main/sloppy-joe.json
sloppy-joe check --json
sloppy-joe check --review-exceptions
sloppy-joe init --register
sloppy-joe init --greenfield --ecosystem npm
sloppy-joe init --from-current
sloppy-joe init --from-current --register
sloppy-joe init > /secure/location/sloppy-joe.json
### Nix```bash
nix profile install github:brennhill/sloppy-joe
Scan-Modi:
sloppy-joe check führt die schnelle lokale Schutzmaßnahme aus. Es erzwingt immer Manifest-Parsing, Lockfile/Sync-, Provenienz- und Nicht-unterstützt-Quelle-Richtlinie. Wenn sich der Abhängigkeits- oder Richtlinienstatus geändert hat oder der letzte erfolgreiche vollständige Scan älter als 24 Stunden ist, empfiehlt es sloppy-joe check --full.sloppy-joe check --full führt den strengen Online-Scan durch und aktualisiert den aufgezeichneten erfolgreichen Vollscan-Status.sloppy-joe check --ci führt dieselbe strenge Abdeckung wie --full durch, jedoch mit CI-orientierter Absicht.sloppy-joe check standardmäßig das runtime-Profil aus. Wenn bereichsbezogene Abhängigkeiten existieren, warnt es und fordert Sie auf, explizite --python-groups-, --python-extras-, --python-platform- und/oder --python-version-Flags für CI/Build-Parität zu übergeben.Rückgabecodes: 0 = keine blockierenden Probleme im gewählten Modus gefunden, 1 = blockierende Probleme gefunden, 2 = Laufzeitfehler.
Unterstützt: JavaScript (npm, pnpm, Yarn, Bun), Python, Rust, Go, Ruby, PHP, JVM (Gradle/Maven) und .NET — automatisch aus Manifest-Dateien erkannt.
Ökosystem-Handbücher: siehe docs/ecosystems/README.md für das aktuelle Vertrauensmodell, unterstützte Funktionen und Fail-Closed-Grenzen für jedes Ökosystem.
Konfigurationsquellen: lokaler Dateipfad, HTTPS-URL oder SLOPPY_JOE_CONFIG-Umgebungsvariable. Die Konfiguration wird niemals aus dem Projektverzeichnis gelesen (siehe CONFIG.md für die Begründung).
Onboarding: Verwenden Sie den Bootstrap-Modus, der zum Repository passt:
sloppy-joe init --greenfield --ecosystem <eco> gibt eine ökosystemspezifische Startrichtlinie für neue Projekte aus. Derzeit sind Greenfield-Voreinstellungen für npm, pypi und cargo implementiert; andere Ökosysteme schlagen mit einem Fehler „noch nicht unterstützt“ fehl. Fügen Sie --register hinzu, um die Konfiguration außerhalb des Repositorys zu schreiben und sicher zu registrieren.sloppy-joe init --from-current untersucht das aktuelle Repository und gibt reine Prüf-Bootstrap-Vorschläge aus. Derzeit ist --from-current nur für Repositorys implementiert, deren First-Party-Code npm und/oder cargo ist; andere Ökosysteme schlagen mit einem Fehler „noch nicht implementiert“ fehl. Fügen Sie --register hinzu, um die generierte Konfiguration zu schreiben und zu registrieren.sloppy-joe init ohne Modus gibt eine neutrale manuelle Vorlage aus.Einzelne Binärdatei. 8 Ökosysteme. 16 Angriffstypen. Null Fehlalarme bei generativen Prüfungen. Konfiguration, die KI-Agenten nicht manipulieren können.
Die meisten Abhängigkeitssicherheitstools prüfen ein oder zwei Dinge – Existenz oder Editierdistanz. sloppy-joe prüft 16 Angriffsvektoren in einem Durchlauf: halluzinierte Pakete, 10 Arten von Typosquatting (Homoglyphen, Scope Squatting, wiederholte Zeichen, Trennzeichenverwirrung, Wortumordnung, benachbarte Vertauschungen, ausgelassene Zeichen, verwirrte Formen, Groß-/Kleinschreibungsvarianten, Versionssuffixe), kanonische Durchsetzung, Versionsalterssperre, Installationsskript-Amplifikation, Abhängigkeitsexplosion, Maintainer-Änderungen und bekannte Schwachstellen über OSV.dev.
Es läuft als einzelne Rust-Binärdatei ohne Laufzeitabhängigkeiten. Es unterstützt alle 8 wichtigen Paket-Ökosysteme. Und seine Konfiguration ist für Sicherheit ausgelegt: niemals aus dem Projektverzeichnis gelesen, von einer URL für CI ladbar, mit klaren Fehlermeldungen, wenn etwas nicht stimmt.
🔶 = Beta/experimentell
Der Angriff: KI generiert import ai_json_helper. Das Paket existiert nicht. Ein Angreifer registriert ai-json-helper auf PyPI mit Malware. Wenn jemand das nächste Mal pip install ausführt, erhält er das bösartige Paket.
Wie sloppy-joe es blockiert: Die Existenzprüfung trifft auf die PyPI-API und erhält einen 404. Build blockiert.``` 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.
### 2. Typosquatting (generative checks + edit distance fallback)
**The attack:** Ein Angreifer registriert `expresz` auf npm – ein Zeichen von `express` entfernt. KI generiert es, oder ein Entwickler vertippt sich. Das Paket existiert, besteht die Existenzprüfung und installiert Schadsoftware.
**How sloppy-joe blocks it:** sloppy-joe führt 10 generative Prüfungen durch, bevor es auf die Edit-Distanz zurückfällt. Jede generative Prüfung erzeugt eine spezifische Mutation des Abhängigkeitsnamens (Zeichen tauschen, Wiederholungen zusammenfassen, Suffixe entfernen, Wörter umstellen, Trennzeichen normalisieren, Homoglyphen ersetzen, Scopes prüfen) und testet auf exakte Übereinstimmung mit bekannten populären Paketen. Dieser Ansatz, inspiriert von der [Rust Foundation's Typomania](https://github.com/rustfoundation/typomania)-Bibliothek, hat nahezu keine Fehlalarme, da er nur bei exakten Treffern nach Mutation auslöst.
Die Levenshtein-Edit-Distanz wird zuletzt als Sicherheitsnetz für neuartige Mutationen verwendet, die keine spezifische Prüfung vorhergesehen hat. Zusammen decken sie sowohl bekannte Angriffsmuster (präzise) als auch unbekannte (breit) ab.```
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.
Der Angriff: expresss (zusätzliches s) oder reeact (zusätzliches e). Dies sind häufige KI-Halluzinationsmuster – das Modell erzeugt plausibel aussehende Namen mit wiederholten Zeichen.
Wie sloppy-joe es blockiert: Die Prüfung auf wiederholte Zeichen reduziert jeweils eine Duplikation und prüft, ob das Ergebnis mit einem bekannten Paket übereinstimmt. expresss → ein s entfernen → express → Übereinstimmung.```
ERROR expresss [similarity/repeated-chars]
'expresss' matches 'express' after removing a repeated character.
Fix: Use 'express' — remove the repeated characters.
### 4. Trennzeichen-Verwirrung
**Der Angriff:** `python-dateutil` vs `python_dateutil` vs `pythondateutil`. In manchen Registries sind dies unterschiedliche Pakete. Ein Angreifer registriert die Variante.
**Wie sloppy-joe es blockt:** Normalisiert alle Trennzeichen (`-`, `_`, `.`) vor dem Vergleich. Wenn die normalisierte Form mit einem bekannten Paket übereinstimmt, wird es markiert.```
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.
Der Angriff: parse-json vs json-parse. Die Levenshtein-Distanz beträgt 8 — unsichtbar für Edit-Distanz-Prüfungen. Aber ein Angreifer kann den umgestellten Namen registrieren.
Wie sloppy-joe es blockiert: Teilt an Trennzeichen, erzeugt alle Permutationen der Segmente und prüft jedes gegen das Korpus. parse-json → permute → json-parse → match.```
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.
### 6. Benachbarte Zeichenvertauschungen
**Der Angriff:** `reqeust` anstelle von `request`. Zwei benachbarte Zeichen vertauscht — ein häufiger Tippfehler, den Angreifer ausnutzen.
**Wie sloppy-joe es blockiert:** Generiert alle Varianten mit benachbarten Vertauschungen des Abhängigkeitsnamens und prüft jede davon gegen das Korpus.```
ERROR reqeusts [similarity/char-swap]
'reqeusts' matches 'requests' with two adjacent characters swapped.
Fix: Use 'requests' — two characters are transposed.
Der Angriff: reqests (fehlendes u) anstelle von requests. Die KI lässt ein Zeichen weg und das Ergebnis ist ein gültig aussehender Name.
Wie sloppy-joe dies blockiert: Fügt jedes Zeichen a-z an jeder Position im Namen ein und prüft, ob ein Ergebnis mit einem bekannten Paket übereinstimmt. reqests + u an Position 3 → requests → Übereinstimmung.```
ERROR reqests [similarity/omitted-char]
'reqests' matches 'requests' with one character inserted.
Fix: Use 'requests' — a character appears to be missing.
### 8. Homoglyphen (optisch identisch wirkende Zeichen)
**Der Angriff:** `rеquests` mit einem kyrillischen `е` (U+0435) anstelle des lateinischen `e` (U+0065). Visuell identisch. Der Paketname sieht genauso aus wie `requests`, verweist aber auf ein anderes, bösartiges Paket.
**Wie sloppy-joe dies blockiert:** Ersetzt 17 bekannte Homoglyphenzeichen (kyrillisch, vollbreit, Schriftvarianten) durch ihre lateinischen Entsprechungen und prüft, ob das Ergebnis mit einem bekannten Paket übereinstimmt.```
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.
Der Angriff: py-utils vs python-utils. Auf PyPI sind das verschiedene Pakete. KI generiert eines, wenn Sie das andere meinen. Ähnlich: github.com vs gitlab.com in Go-Modulen.
Wie sloppy-joe es blockiert: Wendet ökosystemspezifische Substitutionsregeln an (py↔python für PyPI, github↔gitlab für Go) und prüft, ob eine Variante mit einem bekannten Paket übereinstimmt.``` ERROR py-flask [similarity/confused-form] 'py-flask' is a confused form of 'flask'. Fix: Use the canonical name 'flask'.
### 10. Angriffe mit Groß-/Kleinschreibungsvarianten (Groß-/Kleinschreibung-sensitive Registries)
**Der Angriff:** In Go, Maven und Ruby sind `Rails` und `rails` unterschiedliche Pakete. Ein Angreifer registriert die großgeschriebene Variante.
**Wie sloppy-joe dies blockiert:** In Groß-/Kleinschreibung-sensitiven Registries wird jede Groß-/Kleinschreibungsvariante eines bekannten Pakets als Fehler markiert. In Groß-/Kleinschreibung-insensitiven Registries (npm, PyPI, Cargo, NuGet, PHP) sind Groß-/Kleinschreibungsvarianten sicher und werden übersprungen.```
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.
Der Angriff: requests2 oder lodash-4. Die KI hängt eine Versionsnummer an den Paketnamen an, anstatt die Version ordnungsgemäß anzugeben.
Wie sloppy-joe es blockiert: Entfernt nachgestellte Ziffern und Trennzeichen und prüft, ob der Basisname mit einem bekannten Paket übereinstimmt.``` 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.
### 12. Scope Squatting (npm, PHP, Go, JVM)
**Der Angriff:** Ein Angreifer registriert `@typos/lodash` auf npm – ein Zeichen Unterschied zu `@types/lodash`. Oder `larvael/framework` auf Packagist – zwei Zeichen Unterschied zu `laravel/framework`. Oder `github.com/gooogle/protobuf` in Go – ein zusätzliches `o`. Der Scope wirkt auf den ersten Blick legitim. Das Paket wird aufgelöst. Die Malware installiert sich.
Dies ist selten, aber plausibel – und genau für „selten, aber plausibel“ gibt es sloppy-joe. Der `ua-parser-js`-Vorfall im Jahr 2021 war scope-bezogen. Wenn es einem Paket mit Millionen von wöchentlichen Downloads passieren kann, kann es auch Ihrem passieren.
**Wie sloppy-joe es blockiert:** Extrahiert den Scope/Namespace aus dem Abhängigkeitsnamen und vergleicht ihn mit einer Liste bekannter guter Scopes mittels Editierdistanz. Funktioniert für npm (`@scope`), PHP (`vendor/`), Go (`github.com/org`) und 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.
Bitte fügen Sie den zu übersetzenden Markdown-Inhalt ein.``` 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.
### 13. Nicht-kanonische Pakete (kein Angriff — ein Konsistenz-Gate)
**Der Angriff:** Kein Angriff — ein Konsistenzproblem. KI wählt `moment`, weil es in den Trainingsdaten beliebt war, aber Ihr Team verwendet `dayjs`. Verschiedene Teams, die unterschiedliche Pakete für dieselbe Aufgabe nutzen, verursachen Wartungsschulden und Abhängigkeitsaufblähung.
**Wie sloppy-joe es blockiert:** Ihre Konfiguration ordnet jedem kanonischen Paket die abgelehnten Alternativen zu. Wenn eine Abhängigkeit mit einer Alternative übereinstimmt, schlägt der Build fehl.```
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.
Der Angriff: Ein Angreifer kompromittiert das Konto eines Paketbetreuers (oder ein Betreuer wird abtrünnig) und veröffentlicht eine bösartige Patch-Version. Es sieht wie ein normales Update aus. Wenn Ihre CI es sofort installiert, sind Sie kompromittiert, bevor es jemand bemerkt.
Wie sloppy-joe es blockiert: Die Versionsaltersgrenze blockiert jede Abhängigkeit, deren Version vor weniger als min_version_age_hours Stunden veröffentlicht wurde (Standard: 72 Stunden). Dies gibt der Community, Socket.dev und anderen Scannern Zeit, bösartige Versionen zu kennzeichnen.```
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.
### 15. Brandneue Pakete
**Der Angriff:** Ein Paket, das gestern erstellt wurde, 3 Downloads hat und einen Namen trägt, der einem beliebten Paket ähnelt. Hohe Wahrscheinlichkeit, dass es sich um einen Typosquat oder einen Platzhalter für einen zukünftigen Angriff handelt.
**Wie sloppy-joe es blockiert:** Markiert jedes Paket, das vor weniger als 30 Tagen erstellt wurde.```
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.
Der Angriff: Ein Paket mit 12 Downloads, das nur ein Zeichen von requests entfernt ist. Mit ziemlicher Sicherheit ein Typosquat.
Wie sloppy-joe es blockiert: Markiert Pakete mit weniger als 100 Downloads (sofern die Registry Download-Daten bereitstellt — derzeit npm, crates.io, RubyGems).``` ERROR requsets [metadata/low-downloads] 'requsets' has only 12 downloads. Fix: Verify 'requsets' is the package you intend to use.
---
## Unterstützte Ökosysteme
| Ökosystem | Manifest | Lockfile-Richtlinie | Existenz | Metadaten | Altersgrenze |
|-----------|----------|-----------------|:---------:|:--------:|:--------:|
| npm | package.json | `package-lock.json` oder `npm-shrinkwrap.json` erforderlich | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PyPI | `pyproject.toml`, `requirements*.txt`, `Pipfile`, `setup.cfg`, `setup.py` | Poetry wird mit `poetry.lock` vertraut, uv mit `uv.lock`, vollständig hash-gesperrte pip-tools werden nur dann vertraut, wenn der eingecheckte Abhängigkeitsgraph `--index-url` und exakt zugelassene `--extra-index-url`-Werte bindet, und repo-sichtbare benutzerdefinierte Poetry/uv-Indizes können nur durch eine exakte Zulassungsliste `trusted_indexes.pypi` vertraut werden; bei Legacy-Manifesten erscheint bei jedem Durchlauf eine Warnung, es sei denn, `python_enforcement` ist auf `poetry_only` gesetzt | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Cargo | Cargo.toml | `Cargo.lock` erforderlich | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Go | go.mod | `go.sum` für externe Abhängigkeiten erforderlich; nicht erforderlich für reine stdlib- oder vollständig lokale `replace`-Angaben | :white_check_mark: | :x: | :x: |
| Ruby | Gemfile | `Gemfile.lock` erforderlich | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PHP | composer.json | `composer.lock` erforderlich | :white_check_mark: | :x: | :x: |
| JVM (Gradle) | build.gradle / build.gradle.kts | `gradle.lockfile` erforderlich | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| JVM (Maven) | pom.xml | nur Warnung: keine strenge Lockfile-Durchsetzung | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| .NET | *.csproj | `packages.lock.json` erforderlich | :white_check_mark: | :x: | :x: |
Alle Ökosysteme erhalten Existenz-, Ähnlichkeits- und Kanonizitätsprüfungen. Metadaten und Altersgrenzen hängen davon ab, was die Registry-API bereitstellt. Lockfile-Unterstützung ermöglicht transitive Abhängigkeitsscans und exakte Versionsauflösung, sofern das Ökosystem ein vertrauenswürdiges, projekteigenes Lockfile-Modell bereitstellt.
## Schnellstart```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
| Code | Bedeutung |
|---|---|
0 | Alle Prüfungen bestanden |
1 | Probleme gefunden |
2 | Laufzeitfehler |
{ "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" }
**`canonical`** — Schlüssel sind genehmigte Pakete; Werte sind abgelehnte Alternativen.
**`internal`** — Pakete Ihrer Organisation. Überspringt ALLE Prüfungen. Diese ändern sich ständig.
**`allowed`** — geprüfte externe Pakete. Überspringt Existenz- und Ähnlichkeitsprüfungen, unterliegt jedoch weiterhin der Versionsaltersregel.
**`similarity_exceptions`** — exakte Paket-/Kandidat-/Generator-Unterdrückungen für überprüfte Ähnlichkeits-Falschpositive. Verwenden Sie dies, wenn eine bestimmte Ähnlichkeitskante falsch ist, Sie aber dennoch normale Prüfungen für das Paket wünschen.
**`metadata_exceptions`** — exakte überprüfte Metadaten-Unterdrückungen. Derzeit wird nur `metadata/maintainer-change` unterstützt und erfordert eine exakte Übereinstimmung von Paket/Version/vorherigem Herausgeber/aktuellem Herausgeber.
Verwenden Sie `sloppy-joe check --review-exceptions`, wenn Sie Maintainer-Change-Blocker überprüfen müssen. Der Scan blockiert weiterhin normal, aber die menschliche Ausgabe fügt einen Abschnitt `REVIEW EXCEPTIONS` mit Eigentümern, Repository-URL und einem einsatzbereiten `metadata_exceptions`-Snippet hinzu. `--json` enthält dieselben Daten in einem Top-Level-Feld `review_candidates`.
**`min_version_age_hours`** — blockiert jede Version, die vor weniger als dieser Anzahl von Stunden veröffentlicht wurde. Standard: 72 (3 Tage). Auf 0 setzen zum Deaktivieren. Interne Pakete sind ausgenommen.
**`allow_legacy_npm_v1_lockfile`** — erlaubt `lockfileVersion: 1` npm-Lockfiles von npm v5/v6 im Reduced-Confidence-Modus. Standard: `false`. Lassen Sie dies deaktiviert, es sei denn, Sie sind bewusst auf Legacy-npm angewiesen und akzeptieren laute Warnungen sowie reduzierte vertrauenswürdige npm-transitive Abdeckung.
**`python_enforcement`** — steuert die Python-Vertrauensrichtlinie. `prefer_poetry` (Standard) vertraut Poetry-Projekten und uv-Projekten, vertraut vollständig hash-gesperrten pip-tools-Anforderungen nur, wenn der committete Anforderungsgraph `--index-url` und alle nicht-PyPI `--extra-index-url` Werte exakt bindet, und stuft andernfalls pip-tools auf Reduced-Confidence herab. Legacy-Manifeste wie ungehashte `requirements*.txt`, `Pipfile`, `setup.cfg`, `setup.py` und nicht-Poetry/nicht-uv `pyproject.toml` warnen bei jedem Durchlauf. `poetry_only` blockiert diese nicht-Poetry Python-Workflows und erfordert Poetry.
### Konfigurationssicherheit
Die Konfiguration wird **niemals aus dem Projektverzeichnis gelesen**. Ein KI-Agent mit Shell-Zugriff könnte eine im Repository befindliche Konfiguration umschreiben, um zu erlauben, was immer er möchte.
Konfigurationsauflösung:
1. `--config /path/to/config.json` — lokale Datei (CLI-Flag, höchste Priorität)
2. `--config https://example.com/config.json` — von URL abrufen
3. `SLOPPY_JOE_CONFIG=...` — Umgebungsvariable (Dateipfad oder URL)
4. Keine Konfiguration = nur Existenz-, Ähnlichkeits- und Metadatenprüfungen
Fehlerhafte Konfigurationen **scheitern hart** mit umsetzbaren Fehlermeldungen — eine defekte Konfiguration fällt niemals stillschweigend auf keinen Schutz zurück.
Siehe [CONFIG.md](https://github.com/brennhill/sloppy-joe/blob/HEAD/CONFIG.md) für vollständiges Formatreferenz, CI-Integrationsmuster und Beispiele.
Bootstrap-Konfiguration:```bash
sloppy-joe init --greenfield --ecosystem npm
sloppy-joe init --from-current
sloppy-joe init --from-current --register
sloppy-joe init --register
Der schnellste Weg, sloppy-joe zu Ihrer CI-Pipeline hinzuzufügen — lädt ein vorgebautes Binary von GitHub Releases herunter (kein Rust-Toolchain erforderlich):```yaml
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
#### Aktionseingaben
| Eingabe | Beschreibung | Standard |
|-------|-------------|---------|
| `config` | Konfigurationsdateipfad oder HTTPS-URL | *(keine)* |
| `dir` | Zu scannendes Projektverzeichnis | `.` |
| `type` | Ökosystem (`npm`, `pypi`, `cargo`, `go`, `ruby`, `php`, `jvm`, `dotnet`) | automatisch erkennen |
| `deep` | Aktiviert transitive Abhängigkeitsähnlichkeitsprüfungen | `false` |
| `paranoid` | Aktiviert Bitflip-Mutationen | `false` |
| `args` | Zusätzliche CLI-Argumente | *(keine)* |
| `version` | Zu installierende sloppy-joe-Version | `latest` |
#### Beispiele```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'
dependency-guard: script: - cargo install sloppy-joe - sloppy-joe check --ci --config $SLOPPY_JOE_CONFIG
### pre-commit
sloppy-joe arbeitet mit dem [pre-commit](https://pre-commit.com) Framework.
Fügen Sie es in Ihre `.pre-commit-config.yaml` ein:```yaml
# .pre-commit-config.yaml
repos:
- repo: https://github.com/brennhill/sloppy-joe
rev: v1.1.0
hooks:
- id: sloppy-joe
Der Hook führt bei jedem Commit (und optional bei Push) sloppy-joe check aus. Er erkennt Ihr Ökosystem automatisch aus Manifestdateien. Übergeben Sie zusätzliche Argumente über args:```yaml
- id: sloppy-joe
args: [--config, "https://example.com/config.json"]
Oder verwenden Sie einen einfachen Shell-Hook ohne das Framework:```bash
#!/bin/sh
sloppy-joe check || exit 1
sloppy-joe verwendet einen registrierungsbasierten generativen Ansatz zur Ähnlichkeitserkennung. Anstatt jede Abhängigkeit mit einem statischen Korpus und Editierdistanz zu vergleichen (was zu falschen Positiven führt), erzeugt es spezifische Mutationen jedes Abhängigkeitsnamens, fragt die Registry ab, ob die Mutation existiert, und markiert exakte Übereinstimmungen.``` Pipeline (in order):
Ähnlichkeit durchläuft 4 Phasen:
- **Phase 0: Scope squatting** — lokale Prüfung, kein Netzwerk. Vergleicht Scope/Namespace mit bekannten guten Scopes mittels Levenshtein-Distanz.
- **Phase 1: Intra-manifest** — lokale Prüfung. Markiert, wenn zwei Abhängigkeiten im selben Manifest Mutationen voneinander sind.
- **Phase 2: Registry query** — erzeugt Mutationen, führt Batch-Abfragen in der Registry auf Existenz durch, cached Ergebnisse (7-Tage-TTL).
- **Phase 3: Metadata enrichment** — ruft Downloadzahlen und Veröffentlichungsdaten für Treffer ab, um Berichten Nachweise hinzuzufügen.
Jeder Mutationsgenerator taggt seine Ausgabe, sodass der gemeldete Prüftyp (z.B. `similarity/homoglyph`) deterministisch ist – der Generator mit der höchsten Schwere gewinnt, wenn mehrere Generatoren denselben Kandidaten erzeugen.
## CI-Zuverlässigkeit
sloppy-joe ist für CI-Pipelines konzipiert, bei denen flaky Fehler inakzeptabel sind.
**Wiederholung mit Backoff.** Alle Registry-HTTP-Aufrufe wiederholen sich 3 Mal mit exponentiellem Backoff (200ms, 400ms, 800ms) bei vorübergehenden Fehlern (5xx, Timeouts, Verbindungsfehler). Ein einzelner Netzwerkausfall bringt deinen Build nicht zum Scheitern.
**Fail-closed bei Abfragefehlern.** Wenn Registry- oder OSV-Abfragen fehlschlagen, gibt sloppy-joe einen blockierenden Fehler `registry-unreachable` aus, anstatt Prüfungen stillschweigend zu überspringen. Der Scan verlässt sich nicht mehr auf pro-Ökosystem Schwellenwerte oder Sample-Größen-Grenzen, bevor er blockiert.
**Ähnlichkeits-Cache.** Ergebnisse zur Existenz von Mutationen werden für 7 Tage zwischengespeichert. Nach dem ersten Scan werden die meisten Abfragen aus dem Cache bedient, ohne Netzwerkaufrufe. Nur neue Abhängigkeiten lösen Registry-Abfragen aus.
**Lockfile-bewusste Auflösung.** Wenn ein unterstütztes Lockfile vorhanden und vertrauenswürdig ist (`package-lock.json`, `npm-shrinkwrap.json`, `Cargo.lock`, `Gemfile.lock`, `poetry.lock` für Poetry-Projekte, `uv.lock` für uv-Projekte, `composer.lock`, `gradle.lockfile`, `packages.lock.json`), löst sloppy-joe exakte Versionen daraus auf, anstatt aus Bereichen zu raten. Vollständig hash-gesperrte `requirements*.txt` können ebenfalls exakt festgelegte Versionen liefern, und sie werden vollständig vertrauenswürdig, wenn der committete Requirements-Graph seine eigenen `--index-url` und exakt zugelassene `--extra-index-url` Werte bindet.
## Tests
Die Testsuite deckt Ähnlichkeitsprüfungen, Metadaten-Signale, OSV-Verhalten, Konfigurationsparsing und -validierung, Lockfile-Auflösung, Manifest- und Lockfile-Preflight-Richtlinien, Berichtsformatierung und HTTP-Wiederholungslogik ab.```bash
cargo test
Wo andere stärker sind: Socket.dev bietet eine tiefgehende Installationsskript-Analyse mit verhaltensbasierter Erkennung, die weit über den flag-basierten Ansatz von sloppy-joe hinausgeht. cargo-deny bietet eine erstklassige Lizenz-Compliance-Prüfung, aber das liegt bewusst außerhalb des Rahmens von sloppy-joe, da Lizenzrichtlinien ein Compliance-Problem und keine Sicherheitskontrolle für Abhängigkeiten sind. npm audit und pip-audit sind Null-Installations-Optionen für das Schwachstellenscannen in einem einzigen Ökosystem.
Wo sloppy-joe anders ist: Es ist das einzige Tool, das überprüft, ob Pakete tatsächlich in den Registries existieren (und damit KI-Halluzinationen erkennt), 11 Typosquatting-Generatoren mit nahezu keinen Fehlalarmen ausführt, kanonische Paketentscheidungen durchsetzt und seine Konfiguration außerhalb des Repos speichert, damit KI-Agenten ihre eigenen Checks nicht schwächen können.
Apache 2.0
sloppy-joe check-Ausgabe erinnert Sie immer daran, --ci oder --full für CI- und Produktionsgates zu verwenden.| Ökosystem | Erforderliches Manifest | Vertrautes Lockfile / Projektstatus |
|---|
| JavaScript / npm | package.json | package-lock.json oder npm-shrinkwrap.json; Legacy npm v1 standardmäßig blockiert |
| JavaScript / pnpm | package.json | pnpm-lock.yaml |
| JavaScript / Yarn | package.json | yarn.lock |
| JavaScript / Bun | package.json | bun.lock |
| Python | pyproject.toml, requirements*.txt, Pipfile, setup.cfg oder setup.py | Vertrauter Poetry-Pfad verwendet poetry.lock, vertrauter uv-Pfad verwendet uv.lock, und vollständig hash-gesperrte pip-tools werden nur dann vertraut, wenn der committete Abhängigkeitsgraph --index-url und alle --extra-index-url-Werte exakt bindet; im Repository sichtbare Python-Indizes können über trusted_indexes.pypi auf die Whitelist gesetzt werden; vertraute Python-Modi bewerten ein ausgewähltes Installationsprofil nach dem anderen (standardmäßig runtime, explizite Gruppen/Extras/Plattform/Arch/Version über die CLI); Legacy-Manifeste werden standardmäßig mit Warnungen zugelassen |
| Rust | Cargo.toml | Cargo.lock |
| Go | go.mod | go.sum erforderlich für externe Abhängigkeiten |
| Ruby | Gemfile | Gemfile.lock |
| PHP / Composer | composer.json | composer.lock |
| JVM / Gradle | build.gradle oder build.gradle.kts | gradle.lockfile |
| JVM / Maven | pom.xml | nur Warnung: noch kein vertrauter projektlokaler Lockfile-Pfad |
| .NET / NuGet | .csproj | packages.lock.json |
| sloppy-joe | Socket.dev | GuardDog | Phantom Guard | antislopsquat |
|---|
| Existenzprüfung | ✅ | ✅ | ❌ | ✅ | ✅ |
| Ähnlichkeit / Typosquatting | ✅ | ✅ | ✅ | ✅ | ❌ |
| Homoglyphen-Erkennung | ✅ | ❌ | ❌ | ❌ | ❌ |
| Scope Squatting | ✅ | ❌ | ❌ | ❌ | ❌ |
| Kanonische Durchsetzung | ✅ | ❌ | ❌ | ❌ | ❌ |
| Versionsalterssperre | ✅ | ❌ | ❌ | ❌ | ❌ |
| Installationsskript-Amplifikator | ✅ | ✅ | ❌ | ❌ | ❌ |
| Abhängigkeitsexplosion | ✅ | ❌ | ❌ | ❌ | ❌ |
| Maintainer-Änderung | ✅ | ✅ | ❌ | ❌ | ❌ |
| OSV-Schwachstellenprüfung | ✅ | ✅ | ❌ | ❌ | ❌ |
| Konfigurationssicherheit (außerhalb des Repos) | ✅ | N/A | ❌ | ❌ | ❌ |
| Interne + erlaubte Listen | ✅ | ❌ | ❌ | ❌ | ❌ |
| npm | ✅ | ✅ | ✅ | ✅ | ❌ |
| PyPI | ✅ | ✅ | ✅ | ✅ | ✅ |
| Cargo | ✅ | ✅ | ❌ | ✅ | ❌ |
| Go | ✅ | ✅ | ✅ | ❌ | ❌ |
| Ruby | ✅ | ✅ | ✅ | ❌ | ❌ |
| PHP | ✅ | 🔶 | ❌ | ❌ | ❌ |
| JVM (Gradle/Maven) | ✅ | ✅ | ❌ | ❌ | ❌ |
| .NET (NuGet) | ✅ | ✅ | ❌ | ❌ | ❌ |
| Einzelne Binärdatei | ✅ | ❌ | ❌ | ❌ | ❌ |
| Open Source | Apache 2.0 | Kommerziell | Apache 2.0 | MIT | OSS |
| Sprache | Rust | SaaS | Python | Python | Python |
| Merkmal | sloppy-joe | Socket.dev | cargo-deny | pip-audit | npm audit |
|---|
| Erkennung halluzinierter Pakete | ✅ | ❌ | ❌ | ❌ | ❌ |
| Typosquatting-Erkennung | ✅ 11 Generatoren | Teilweise | ❌ | ❌ | ❌ |
| Durchsetzung kanonischer Namen | ✅ | ❌ | ❌ | ❌ | ❌ |
| Scannen bekannter Schwachstellen | ✅ über OSV | ✅ | ✅ | ✅ | ✅ |
| Installationsskript-Analyse | Basis (Flag + kein Repo) | ✅ Tiefgehende Analyse | ❌ | ❌ | ❌ |
| Lizenz-Compliance | OOS: Compliance, nicht Sicherheit | ✅ | ✅ Hervorragend | OOS: Compliance, nicht Sicherheit | OOS: Compliance, nicht Sicherheit |
| Multi-Ökosystem | 8 Ökosysteme | npm, PyPI, Go, Ruby, Java, .NET | Nur Rust | Nur Python | Nur npm |
| KI-Agenten-Sicherheit (Konfiguration außerhalb des Repos) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Offline-/CI-freundlich | ✅ Läuft überall | Erfordert Socket-Plattform | ✅ | ✅ | ✅ |
| Kostenlos / Open Source | Apache 2.0 | Kostenloser Tarif + kostenpflichtig | Apache 2.0 | Apache 2.0 | Integriert |