Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
sloppy-joe — Protege contra ataques de cadena de suministro, slopsquatting y typosquatting provenientes de dependencias y código. | Kitploit
Herramientas/GitHubGitHub/brennhill/sloppy-joe
Análisis EstáticoEscáneres de VulnerabilidadesAnálisis de CódigoDevSecOpsDetección de SecretosInteligencia de AmenazasSeguridad de Cadena de SuministroAprendizaje y Educación
GitHubbrennhill/sloppy-joe

sloppy-joe

Protege contra ataques de cadena de suministro, slopsquatting y typosquatting provenientes de dependencias y código.

Ver Repositorio
321hace 4 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

sloppy-joe

Detecta dependencias alucinadas, typo-squatted y no canónicas
antes de que lleguen a producción.

cargo install sloppy-joe


El ataque a la cadena de suministro de LiteLLM (marzo de 2026) comprometió un paquete con 97 millones de descargas mensuales. Los atacantes robaron credenciales de publicación, lanzaron versiones maliciosas que recolectaron claves SSH, credenciales en la nube y secretos de K8s. La compuerta de edad de versión predeterminada de 72 horas de sloppy-joe habría bloqueado ambas versiones envenenadas: fueron descubiertas en cuestión de horas, mucho antes de que la compuerta se abriera. Si ejecutas sloppy-joe check en CI, este ataque falla. Análisis completo

Los generadores de código con IA alucinan nombres de paquetes ~20% de las veces. Los atacantes registran esos nombres y esperan. sloppy-joe los detecta en CI antes de que se ejecuten npm install o pip install.

Cómo usar```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

Modos de escaneo:

  • sloppy-joe check ejecuta el guardarraíl local rápido. Siempre impone el análisis del manifiesto, lockfile/sync, procedencia y la política de fuentes no soportadas. Si el estado de las dependencias o la política cambió, o si el último escaneo completo exitoso tiene más de 24 horas, recomienda sloppy-joe check --full.
  • sloppy-joe check --full ejecuta el escaneo estricto en línea y refresca el estado registrado del escaneo completo exitoso.
  • sloppy-joe check --ci ejecuta la misma cobertura estricta que --full, con intención orientada a CI.
  • Para Python, sloppy-joe check evalúa el perfil runtime por defecto. Si existen dependencias con ámbito, advierte y te indica que pases explícitamente las banderas --python-groups, --python-extras, --python-platform y/o --python-version para paridad con CI/build.
  • La salida legible para humanos de sloppy-joe check siempre recuerda usar o para CI y control de producción.

Códigos de salida: 0 = no se encontraron problemas bloqueantes en el modo seleccionado, 1 = se encontraron problemas bloqueantes, 2 = error de ejecución.

Soporta: JavaScript (npm, pnpm, Yarn, Bun), Python, Rust, Go, Ruby, PHP, JVM (Gradle/Maven) y .NET — detectados automáticamente a partir de los archivos de manifiesto.

Guías de ecosistemas: consulta docs/ecosystems/README.md para conocer el modelo de confianza actual, las funciones compatibles y los límites de fallo cerrado para cada ecosistema.

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

Fuentes de configuración: ruta de archivo local, URL HTTPS o variable de entorno SLOPPY_JOE_CONFIG. La configuración nunca se lee desde el directorio del proyecto (ver CONFIG.md para saber por qué).

Incorporación: usa el modo de arranque que coincida con el repositorio:

  • sloppy-joe init --greenfield --ecosystem <eco> imprime una política de inicio específica del ecosistema para nuevos proyectos. Actualmente, los ajustes predefinidos de greenfield están implementados para npm, pypi y cargo; otros ecosistemas fallan con un error "not supported yet". Añade --register para escribirlo fuera del repositorio y registrarlo de forma segura.
  • sloppy-joe init --from-current inspecciona el repositorio actual e imprime sugerencias de arranque solo para revisión. Actualmente, --from-current solo está implementado para repositorios cuyo código propio es npm y/o cargo; otros ecosistemas fallan de forma cerrada con un error "not implemented yet". Añade --register para escribir y registrar la configuración generada.
  • sloppy-joe init sin modo imprime una plantilla manual neutra.

¿Por qué sloppy-joe?

Un solo binario. 8 ecosistemas. 16 tipos de ataque. Cero falsos positivos en comprobaciones generativas. Configuración que los agentes de IA no pueden manipular.

La mayoría de las herramientas de seguridad de dependencias verifican una o dos cosas — existencia o distancia de edición. sloppy-joe comprueba 16 vectores de ataque en una sola pasada: paquetes alucinados, 10 tipos de typosquatting (homoglifos, squatting de ámbito, caracteres repetidos, confusión de separadores, reordenación de palabras, intercambios adyacentes, caracteres omitidos, formas confusas, variantes de mayúsculas/minúsculas, sufijos de versión), aplicación canónica, control de antigüedad de versión, amplificación de scripts de instalación, explosión de dependencias, cambios de mantenedor y vulnerabilidades conocidas mediante OSV.dev.

Se ejecuta como un único binario Rust sin dependencias de ejecución. Soporta los 8 ecosistemas principales de paquetes. Y su configuración está diseñada para la seguridad: nunca se lee desde el directorio del proyecto, se puede cargar desde una URL para CI, con mensajes de error claros cuando algo está mal.

🔶 = beta/experimental


Cómo funciona cada ataque (y cómo lo bloquea sloppy-joe)

1. Paquetes alucinados

El ataque: La IA genera import ai_json_helper. El paquete no existe. Un atacante registra ai-json-helper en PyPI con malware. La próxima vez que alguien ejecute pip install, obtendrá el paquete malicioso.

Cómo lo bloquea sloppy-joe: La comprobación de existencia consulta la API de PyPI y recibe un 404. Compilación bloqueada.``` 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. Typosquatting (verificaciones generativas + recurso de distancia de edición)

**El ataque:** Un atacante registra `expresz` en npm — a un carácter de `express`. La IA lo genera, o un desarrollador lo escribe mal. El paquete existe, pasa la verificación de existencia e instala malware.

**Cómo sloppy-joe lo bloquea:** sloppy-joe ejecuta 10 verificaciones generativas antes de recurrir a la distancia de edición. Cada verificación generativa produce una mutación específica del nombre de la dependencia (intercambiar caracteres, colapsar repeticiones, eliminar sufijos, reordenar palabras, normalizar separadores, reemplazar homóglifos, verificar ámbitos) y prueba una coincidencia exacta con paquetes populares conocidos. Este enfoque, inspirado en la biblioteca [Typomania de la Rust Foundation](https://github.com/rustfoundation/typomania), tiene casi cero falsos positivos porque solo se activa con coincidencias exactas después de la mutación.

La distancia de edición de Levenshtein se ejecuta al final como una red de seguridad para mutaciones novedosas que ninguna verificación específica anticipó. Juntos, cubren tanto patrones de ataque conocidos (con precisión) como desconocidos (de manera amplia).```
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. Caracteres repetidos

El ataque: expresss (s extra) o reeact (e extra). Estos son patrones comunes de alucinación de IA: el modelo genera nombres de apariencia plausible con caracteres repetidos.

Cómo lo bloquea sloppy-joe: La verificación de caracteres repetidos elimina un duplicado a la vez y comprueba si el resultado coincide con un paquete conocido. expresss → eliminar una s → express → coincidencia.``` ERROR expresss [similarity/repeated-chars] 'expresss' matches 'express' after removing a repeated character. Fix: Use 'express' — remove the repeated characters.

root@kitploit:~
### 4. Confusión de separadores

**El ataque:** `python-dateutil` vs `python_dateutil` vs `pythondateutil`. En algunos registros, estos son paquetes diferentes. Un atacante registra la variante.

**Cómo sloppy-joe lo bloquea:** Normaliza todos los separadores (`-`, `_`, `.`) antes de la comparación. Si la forma normalizada coincide con un paquete conocido, se marca.```
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. Reordenamiento de palabras

El ataque: parse-json vs json-parse. La distancia de Levenshtein es 8 — invisible para las comprobaciones de distancia de edición. Pero un atacante puede registrar el nombre reordenado.

Cómo lo bloquea sloppy-joe: Divide en separadores, genera todas las permutaciones de los segmentos y verifica cada una contra el corpus. parse-json → permutar → json-parse → coincidencia.``` 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. Intercambios de caracteres adyacentes

**El ataque:** `reqeust` en lugar de `request`. Dos caracteres adyacentes transpuestos — un error tipográfico común que los atacantes aprovechan.

**Cómo sloppy-joe lo bloquea:** Genera todas las variantes de intercambio adyacente del nombre de la dependencia y verifica cada una contra el corpus.```
ERROR reqeusts [similarity/char-swap]
      'reqeusts' matches 'requests' with two adjacent characters swapped.
 Fix: Use 'requests' — two characters are transposed.

7. Caracteres omitidos

El ataque: reqests (falta la u) en lugar de requests. La IA omite un carácter y el resultado es un nombre de apariencia válida.

Cómo lo bloquea sloppy-joe: Inserta cada carácter de la a a la z en cada posición del nombre y verifica si algún resultado coincide con un paquete conocido. reqests + u en la posición 3 → requests → coincidencia.``` ERROR reqests [similarity/omitted-char] 'reqests' matches 'requests' with one character inserted. Fix: Use 'requests' — a character appears to be missing.

root@kitploit:~
### 8. Homoglifos (similitudes visuales)

**El ataque:** `rеquests` con una `е` cirílica (U+0435) en lugar de la `e` latina (U+0065). Visualmente idéntico. El nombre del paquete se ve exactamente como `requests` pero se resuelve a un paquete malicioso diferente.

**Cómo sloppy-joe lo bloquea:** Reemplaza 17 caracteres de homoglifos conocidos (cirílicos, de ancho completo, variantes de script) con sus equivalentes latinos y comprueba si el resultado coincide con un paquete conocido.```
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. Formas confusas de ecosistema

El ataque: py-utils vs python-utils. En PyPI, estos son paquetes diferentes. La IA genera uno cuando querías el otro. Similarmente, github.com vs gitlab.com en módulos Go.

Cómo sloppy-joe lo bloquea: Aplica reglas de sustitución específicas del ecosistema (py↔python para PyPI, github↔gitlab para Go) y verifica si alguna variante coincide con un paquete conocido.``` ERROR py-flask [similarity/confused-form] 'py-flask' is a confused form of 'flask'. Fix: Use the canonical name 'flask'.

root@kitploit:~
### 10. Ataques de variantes de mayúsculas/minúsculas (registros sensibles a mayúsculas/minúsculas)

**El ataque:** En Go, Maven y Ruby, `Rails` y `rails` son paquetes diferentes. Un atacante registra la variante en mayúsculas.

**Cómo lo bloquea sloppy-joe:** En registros sensibles a mayúsculas/minúsculas, cualquier variante de mayúsculas/minúsculas de un paquete conocido se marca como un error. En registros insensibles a mayúsculas/minúsculas (npm, PyPI, Cargo, NuGet, PHP), las variantes de mayúsculas/minúsculas son seguras y se omiten.```
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. Suplantación de sufijo de versión

El ataque: requests2 o lodash-4. La IA añade un número de versión al nombre del paquete en lugar de especificar la versión correctamente.

Cómo lo bloquea sloppy-joe: Elimina los dígitos y separadores finales y comprueba si el nombre base coincide con un paquete conocido.``` 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. Suplantación de alcance (npm, PHP, Go, JVM)

**El ataque:** Un atacante registra `@typos/lodash` en npm — a un carácter de `@types/lodash`. O `larvael/framework` en Packagist — a dos caracteres de `laravel/framework`. O `github.com/gooogle/protobuf` en Go — una `o` extra. El alcance parece legítimo a simple vista. El paquete se resuelve. El malware se instala.

Esto es raro pero plausible — y "raro pero plausible" es exactamente para lo que existe sloppy-joe. El incidente de `ua-parser-js` en 2021 estaba relacionado con el alcance. Si puede ocurrirle a un paquete con millones de descargas semanales, puede ocurrirle al tuyo.

**Cómo lo bloquea sloppy-joe:** Extrae el alcance/namespace del nombre de la dependencia y lo compara contra una lista de alcances conocidos como seguros usando la distancia de edición. Funciona en npm (`@scope`), PHP (`vendor/`), Go (`github.com/org`) y 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.
root@kitploit:~
wifi_eap_hammer.sh --bssid 22:6a:7d:4f:c2:4a --interface wlan0 --essid "SecureWifi" --wordlist rockyou.txt --daemon

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. Paquetes no canónicos (no es un ataque — una puerta de consistencia)

**El ataque:** No es un ataque — es un problema de consistencia. La IA elige `moment` porque era popular en los datos de entrenamiento, pero tu equipo usa `dayjs`. Diferentes equipos usando diferentes paquetes para la misma tarea genera deuda de mantenimiento e hinchazón de dependencias.

**Cómo lo bloquea sloppy-joe:** Tu configuración asigna cada paquete canónico a sus alternativas rechazadas. Si una dependencia coincide con una alternativa, la compilación falla.```
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. Versiones demasiado nuevas (bomba de tiempo en la cadena de suministro)

El ataque: Un atacante compromete la cuenta de un mantenedor de paquetes (o un mantenedor se vuelve malintencionado) y publica una versión de parche maliciosa. Parece una actualización normal. Si tu CI la instala inmediatamente, estás comprometido antes de que nadie se dé cuenta.

Cómo lo bloquea sloppy-joe: La puerta de antigüedad de versión bloquea cualquier dependencia cuya versión se haya publicado hace menos de min_version_age_hours (predeterminado: 72 horas). Esto le da tiempo a la comunidad, Socket.dev y otros escáneres para marcar versiones maliciosas.``` 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. Paquetes completamente nuevos

**El ataque:** Un paquete creado ayer con 3 descargas que tiene un nombre similar a un paquete popular. Alta probabilidad de ser un typosquat o un marcador de posición para un ataque futuro.

**Cómo lo bloquea sloppy-joe:** Marca cualquier paquete creado hace menos de 30 días.```
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. Paquetes con pocas descargas

El ataque: Un paquete con 12 descargas que resulta estar a un carácter de diferencia de requests. Casi con total seguridad un typosquat.

Cómo sloppy-joe lo bloquea: Marca los paquetes con menos de 100 descargas (donde el registro proporciona datos de descargas — actualmente 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:~
## Ecosistemas compatibles

| Ecosistema | Manifiesto | Política de archivo de bloqueo | Existencia | Metadatos | Control de antigüedad |
|-----------|----------|-----------------|:---------:|:--------:|:--------:|
| npm | package.json | `package-lock.json` o `npm-shrinkwrap.json` requerido | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PyPI | `pyproject.toml`, `requirements*.txt`, `Pipfile`, `setup.cfg`, `setup.py` | Poetry es confiable con `poetry.lock`, uv es confiable con `uv.lock`, pip-tools con bloqueo de hash completo es confiable solo cuando el grafo de requisitos comprometido vincula `--index-url` y valores exactos permitidos de `--extra-index-url`, y los índices personalizados de Poetry/uv visibles en el repositorio solo se pueden confiar mediante la lista de permitidos exacta `trusted_indexes.pypi`; los manifiestos heredados advierten en cada ejecución a menos que `python_enforcement` sea `poetry_only` | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Cargo | Cargo.toml | `Cargo.lock` requerido | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Go | go.mod | `go.sum` requerido para dependencias externas; no requerido para stdlib-only o `replace` totalmente local | :white_check_mark: | :x: | :x: |
| Ruby | Gemfile | `Gemfile.lock` requerido | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| PHP | composer.json | `composer.lock` requerido | :white_check_mark: | :x: | :x: |
| JVM (Gradle) | build.gradle / build.gradle.kts | `gradle.lockfile` requerido | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| JVM (Maven) | pom.xml | solo advertencia: sin aplicación estricta de archivo de bloqueo | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| .NET | *.csproj | `packages.lock.json` requerido | :white_check_mark: | :x: | :x: |

Todos los ecosistemas reciben verificaciones de existencia, similitud y canónicas. Los metadatos y el control de antigüedad dependen de lo que expone la API del registro. El soporte de archivos de bloqueo permite el escaneo de dependencias transitivas y la resolución exacta de versiones donde el ecosistema proporciona un modelo de archivo de bloqueo local de proyecto confiable.

## Inicio Rápido```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

Códigos de Salida

CódigoSignificado
0Todas las comprobaciones superadas
1Problemas encontrados
2Error de ejecución

Configuración```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`** — las claves son paquetes aprobados; los valores son alternativas rechazadas.

**`internal`** — paquetes de su organización. Omitir TODAS las comprobaciones. Cambian constantemente.

**`allowed`** — paquetes externos verificados. Omitir existencia + similitud, pero aún sujetos a la puerta de antigüedad de versión.

**`similarity_exceptions`** — supresiones exactas de paquete/candidato/generador para falsos positivos de similitud revisados. Úselo cuando un borde de similitud específico sea incorrecto pero aún desee comprobaciones normales en el paquete.

**`metadata_exceptions`** — supresiones exactas de metadatos revisados. Actualmente solo admite `metadata/maintainer-change` y requiere una coincidencia exacta de paquete/versión/publicador-anterior/publicador-actual.

Use `sloppy-joe check --review-exceptions` cuando necesite revisar bloqueos de cambio de mantenedor. El escaneo aún bloquea normalmente, pero la salida humana agrega una sección `REVIEW EXCEPTIONS` con propietarios, URL del repositorio y un fragmento `metadata_exceptions` listo para pegar. `--json` incluye los mismos datos en un campo de nivel superior `review_candidates`.

**`min_version_age_hours`** — bloquear cualquier versión publicada hace menos de esta cantidad de horas. Predeterminado: 72 (3 días). Establecer en 0 para deshabilitar. Los paquetes internos están exentos.

**`allow_legacy_npm_v1_lockfile`** — permitir `lockfileVersion: 1` archivos de bloqueo npm de npm v5/v6 en modo de confianza reducida. Predeterminado: `false`. Manténgalo desactivado a menos que esté intencionalmente atascado en npm heredado y acepte advertencias fuertes más cobertura transitiva npm de confianza reducida.

**`python_enforcement`** — controla la política de confianza de Python. `prefer_poetry` (predeterminado) confía en proyectos Poetry y proyectos uv, confía en requisitos de pip-tools completamente bloqueados por hash solo cuando el gráfico de requisitos comprometido vincula `--index-url` y cualquier valor `--extra-index-url` que no sea PyPI exactamente, y de lo contrario degrada pip-tools a confianza reducida. Manifiestos heredados como `requirements*.txt` sin hash, `Pipfile`, `setup.cfg`, `setup.py` y `pyproject.toml` que no sean de Poetry/uv advierten en cada ejecución. `poetry_only` bloquea esos flujos de trabajo Python no Poetry y requiere Poetry.

### Seguridad de la Configuración

La configuración **nunca se lee desde el directorio del proyecto**. Un agente de IA con acceso al shell podría reescribir una configuración en el repositorio para permitir lo que quiera.

Resolución de la configuración:
1. `--config /path/to/config.json` — archivo local (bandera CLI, prioridad máxima)
2. `--config https://example.com/config.json` — obtener desde URL
3. `SLOPPY_JOE_CONFIG=...` — variable de entorno (ruta de archivo o URL)
4. Sin configuración = solo comprobaciones de existencia + similitud + metadatos

Las configuraciones mal formadas **fallan duramente** con mensajes de error procesables: una configuración rota nunca retrocede silenciosamente a ninguna protección.

Consulte [CONFIG.md](https://github.com/brennhill/sloppy-joe/blob/HEAD/CONFIG.md) para obtener la referencia de formato completa, patrones de integración CI y ejemplos.

Configuración de arranque:```bash
sloppy-joe init --greenfield --ecosystem npm
sloppy-joe init --from-current
sloppy-joe init --from-current --register
sloppy-joe init --register

Integración CI

GitHub Actions

La forma más rápida de agregar sloppy-joe a tu pipeline de CI — descarga un binario precompilado desde GitHub Releases (no requiere 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:~
#### Entradas de acción

| Entrada | Descripción | Predeterminado |
|---------|-------------|----------------|
| `config` | Ruta de archivo de configuración o URL HTTPS | *(ninguno)* |
| `dir` | Directorio del proyecto a escanear | `.` |
| `type` | Ecosistema (`npm`, `pypi`, `cargo`, `go`, `ruby`, `php`, `jvm`, `dotnet`) | detección automática |
| `deep` | Habilitar comprobaciones de similitud de dependencias transitivas | `false` |
| `paranoid` | Habilitar mutaciones de bitflip | `false` |
| `args` | Argumentos CLI adicionales | *(ninguno)* |
| `version` | versión de sloppy-joe a instalar | `latest` |

#### Ejemplos```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 funciona con el framework [pre-commit](https://pre-commit.com).
Agrégalo a tu `.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

El hook ejecuta sloppy-joe check en cada commit (y opcionalmente en push). Detecta automáticamente tu ecosistema a partir de los archivos de manifiesto. Pasa argumentos adicionales a través de args:```yaml - id: sloppy-joe args: [--config, "https://example.com/config.json"]

root@kitploit:~
O usa un simple hook de shell sin el framework:```bash
#!/bin/sh
sloppy-joe check || exit 1

Arquitectura

sloppy-joe utiliza un enfoque generativo basado en registros para la detección de similitudes. En lugar de comparar cada dependencia contra un corpus estático con distancia de edición (lo que genera falsos positivos), genera mutaciones específicas de cada nombre de dependencia, consulta el registro para verificar si la mutación existe y marca las coincidencias exactas.``` 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:~
Similitud ejecuta 4 fases:
- **Fase 0: Suplantación de ámbito** — verificación local, sin red. Compara el ámbito/namespace con ámbitos conocidos mediante distancia de Levenshtein.
- **Fase 1: Intra-manifiesto** — verificación local. Señala cuando dos dependencias en el mismo manifiesto son mutaciones entre sí.
- **Fase 2: Consulta al registro** — genera mutaciones, consulta por lotes al registro para verificar existencia, almacena en caché los resultados (TTL de 7 días).
- **Fase 3: Enriquecimiento de metadatos** — obtiene conteos de descargas y fechas de publicación para coincidencias, añadiendo evidencia a los informes.

Cada generador de mutaciones etiqueta su salida, por lo que el tipo de verificación reportado (ej., `similarity/homoglyph`) es determinista: el generador de mayor severidad gana cuando múltiples generadores producen el mismo candidato.

## Fiabilidad en CI

sloppy-joe está diseñado para pipelines de CI donde fallos inestables son inaceptables.

**Reintento con retroceso.** Todas las llamadas HTTP al registro reintentan 3 veces con retroceso exponencial (200ms, 400ms, 800ms) en fallos transitorios (5xx, tiempos de espera, errores de conexión). Un solo error de red no arruinará tu build.

**Fallo cerrado en errores de consulta.** Si las consultas al registro o a OSV fallan, sloppy-joe emite un error bloqueante `registry-unreachable` en lugar de saltar silenciosamente las verificaciones. El escaneo ya no depende de umbrales por ecosistema o límites de tamaño de muestra antes de bloquear.

**Caché de similitud.** Los resultados de existencia de mutaciones se almacenan en caché durante 7 días. Después del primer escaneo, la mayoría de las consultas se sirven desde la caché sin llamadas de red. Solo las dependencias nuevas activan consultas al registro.

**Resolución consciente del archivo de bloqueo.** Cuando un archivo de bloqueo compatible está presente y es confiable (`package-lock.json`, `npm-shrinkwrap.json`, `Cargo.lock`, `Gemfile.lock`, `poetry.lock` para proyectos Poetry, `uv.lock` para proyectos uv, `composer.lock`, `gradle.lockfile`, `packages.lock.json`), sloppy-joe resuelve versiones exactas a partir de él en lugar de adivinarlas a partir de rangos. Los archivos `requirements*.txt` con hash completo también pueden proporcionar versiones exactas fijadas, y se vuelven completamente confiables cuando el grafo de requerimientos comprometido vincula su propio `--index-url` y valores `--extra-index-url` exactos en lista blanca.

## Pruebas

La suite de pruebas cubre verificaciones de similitud, señales de metadatos, comportamiento de OSV, análisis y validación de configuración, resolución de archivos de bloqueo, política de pre-vuelo para manifiestos y archivos de bloqueo, formato de informes y lógica de reintentos HTTP.```bash
cargo test

Construido sobre

  • Typomania — Biblioteca de suplantación de escritura de Rust Foundation, que inspiró el enfoque de mutación generativa (sloppy-joe implementa sus propios generadores en lugar de usar la crate directamente)
  • strsim — Distancia de Levenshtein, usada para detección de suplantación de ámbitos (scope squatting)
  • reqwest — Cliente HTTP asíncrono con reintentos para consultas a registros
  • OSV.dev — Base de datos de vulnerabilidades conocidas para detección de paquetes maliciosos

Cómo se compara sloppy-joe

Donde otros son más fuertes: Socket.dev realiza un análisis profundo de scripts de instalación con detección conductual que va mucho más allá del enfoque basado en banderas de sloppy-joe. cargo-deny tiene una verificación de cumplimiento de licencias de primer nivel, pero eso queda intencionalmente fuera del alcance de sloppy-joe porque la política de licencias es un problema de cumplimiento, no un control de seguridad de dependencias. npm audit y pip-audit son opciones sin instalación para escaneo de vulnerabilidades de un solo ecosistema.

Donde sloppy-joe es diferente: Es la única herramienta que verifica que los paquetes realmente existan en los registros (detectando alucinaciones de IA), ejecuta 11 generadores de suplantación de escritura con falsos positivos casi nulos, impone opciones de paquetes canónicos y mantiene su configuración fuera del repositorio para que los agentes de IA no puedan debilitar sus propias comprobaciones.

Licencia

Apache 2.0

Descargar herramienta
--ci
--full
EcosistemaManifiesto requeridoLockfile / estado de proyecto confiable
JavaScript / npmpackage.jsonpackage-lock.json o npm-shrinkwrap.json; npm v1 heredado bloqueado por defecto
JavaScript / pnpmpackage.jsonpnpm-lock.yaml
JavaScript / Yarnpackage.jsonyarn.lock
JavaScript / Bunpackage.jsonbun.lock
Pythonpyproject.toml, requirements*.txt, Pipfile, setup.cfg, o setup.pyLa ruta de Poetry confiable usa poetry.lock, la ruta de uv confiable usa uv.lock, y pip-tools con hash completo solo es confiable cuando el grafo de requisitos comprometido vincula exactamente los valores de --index-url y cualquier --extra-index-url; los índices de Python visibles en el repositorio pueden ser permitidos mediante trusted_indexes.pypi; los modos de Python confiables evalúan un perfil de instalación seleccionado a la vez (runtime por defecto, grupos/extras/plataforma/arquitectura/versión explícitos mediante CLI); los manifiestos heredados se permiten con advertencias por defecto
RustCargo.tomlCargo.lock
Gogo.modgo.sum requerido para dependencias externas
RubyGemfileGemfile.lock
PHP / Composercomposer.jsoncomposer.lock
JVM / Gradlebuild.gradle o build.gradle.ktsgradle.lockfile
JVM / Mavenpom.xmlsolo advertencia: aún no hay ruta de lockfile local de proyecto confiable
.NET / NuGet.csprojpackages.lock.json
sloppy-joeSocket.devGuardDogPhantom Guardantislopsquat
Comprobación de existencia✅✅❌✅✅
Similitud / typosquat✅✅✅✅❌
Detección de homoglifos✅❌❌❌❌
Squatting de ámbito✅❌❌❌❌
Aplicación canónica✅❌❌❌❌
Control de antigüedad de versión✅❌❌❌❌
Amplificación de script de instalación✅✅❌❌❌
Explosión de dependencias✅❌❌❌❌
Cambio de mantenedor✅✅❌❌❌
Comprobación de vulnerabilidades OSV✅✅❌❌❌
Seguridad de configuración (fuera del repositorio)✅N/A❌❌❌
Listas internas y permitidas✅❌❌❌❌
npm✅✅✅✅❌
PyPI✅✅✅✅✅
Cargo✅✅❌✅❌
Go✅✅✅❌❌
Ruby✅✅✅❌❌
PHP✅🔶❌❌❌
JVM (Gradle/Maven)✅✅❌❌❌
.NET (NuGet)✅✅❌❌❌
Binario único✅❌❌❌❌
Código abiertoApache 2.0CommercialApache 2.0MITOSS
LenguajeRustSaaSPythonPythonPython
Característicasloppy-joeSocket.devcargo-denypip-auditnpm audit
Detección de paquetes alucinados✅❌❌❌❌
Detección de suplantación de escritura✅ 11 generadoresParcial❌❌❌
Imposición de nombre canónico✅❌❌❌❌
Escaneo de vulnerabilidades conocidas✅ vía OSV✅✅✅✅
Análisis de scripts de instalaciónBásico (bandera + sin repositorio)✅ Análisis profundo❌❌❌
Cumplimiento de licenciasFuera de alcance: cumplimiento, no seguridad✅✅ ExcelenteFuera de alcance: cumplimiento, no seguridadFuera de alcance: cumplimiento, no seguridad
Multi-ecosistema8 ecosistemasnpm, PyPI, Go, Ruby, Java, .NETSolo RustSolo PythonSolo npm
Seguridad para agentes de IA (configuración externa al repositorio)✅❌❌❌❌
Amigable sin conexión/CI✅ Funciona en cualquier lugarRequiere plataforma Socket✅✅✅
Gratuito / código abiertoApache 2.0Plan gratuito + pagoApache 2.0Apache 2.0Integrado