
🐍 🔍 GuardDog es una herramienta CLI para identificar paquetes maliciosos de PyPI y npm
# GuardDog
[](https://github.com/DataDog/guarddog/actions/workflows/checks.yml)
[](https://securityscorecards.dev/viewer/?uri=github.com/DataDog/guarddog)
[](https://www.bestpractices.dev/projects/12273)
<p align="center">
<img src="https://raw.githubusercontent.com/DataDog/guarddog/v3/docs/images/logo.png?raw=true" alt="GuardDog" width="300" />
</p>
GuardDog es una herramienta CLI que identifica paquetes maliciosos de PyPI y npm, módulos de Go, crates de Rust, RubyGems, acciones de GitHub o extensiones de VSCode. Ejecuta análisis estático sobre el código fuente de los paquetes (mediante reglas YARA) y analiza los metadatos de los paquetes para detectar ataques a la cadena de suministro.
**Qué hace diferente a GuardDog:** En lugar de simplemente listar patrones sospechosos, GuardDog correlaciona los hallazgos para identificar **riesgos** reales basados en cadenas de ataque. Un paquete necesita tanto la **capacidad** de realizar una acción (p. ej., acceso a red) como un **indicador de amenaza** (p. ej., dominio sospechoso) en el mismo archivo para ser marcado como de alto riesgo.
Descarga y escanea código de:
* NPM: Paquetes alojados en [npmjs.org](https://www.npmjs.com/)
* PyPI: Archivos fuente (tar.gz) de paquetes alojados en [PyPI.org](https://pypi.org/)
* Go: Archivos fuente de GoLang de repositorios alojados en [GitHub.com](https://github.com)
* Rust: Crates alojados en [crates.io](https://crates.io/)
* RubyGems: Paquetes Gem alojados en [rubygems.org](https://rubygems.org/)
* GitHub Actions: Archivos fuente de JavaScript de repositorios alojados en [GitHub.com](https://github.com)
* Extensiones de VSCode: Paquetes de extensiones (.vsix) alojados en [marketplace.visualstudio.com](https://marketplace.visualstudio.com/)

## Cómo funciona GuardDog
GuardDog utiliza un **modelo de detección basado en riesgos** que correlaciona las capacidades del código con los indicadores de amenaza:
1. **Detección**: Las reglas identifican **capacidades** (lo que el código *puede* hacer) o **amenazas** (indicadores sospechosos)
2. **Correlación**: Las capacidades y amenazas encontradas en el mismo archivo forman **riesgos** (las coincidencias entre archivos también forman riesgos, con severidad reducida)
3. **Puntuación**: Los riesgos se puntúan (0-10) según la completitud y sofisticación de la cadena de ataque
4. **Informe**: Los paquetes reciben una calificación de severidad (baja/media/alta) con un desglose detallado de riesgos
### ¿Por qué este enfoque?
Las herramientas SAST tradicionales marcan cada patrón sospechoso de forma independiente, lo que provoca fatiga de alertas. GuardDog entiende que:
- **Solo la capacidad** no es maliciosa (las bibliotecas de red deberían hacer solicitudes HTTP)
- **Solo los indicadores de amenaza** podrían ser falsos positivos (fixtures de pruebas, documentación)
- **Capacidad + Amenaza juntas** indican un riesgo real (código que puede *y va a* hacer algo malicioso)
### Puntuación de riesgos
Los paquetes reciben una puntuación de **0-10** basada en cuatro factores:
| Factor | Peso | Descripción |
|--------|--------|-------------|
| **Severidad** | 30% | Hallazgo de mayor severidad (baja/media/alta) |
| **Cadena de ataque** | 20% | Presencia de etapas de ataque completas (temprana → media/tardía) |
| **Especificidad** | 30% | Qué tan específicos son los patrones del malware frente al código legítimo |
| **Sofisticación** | 20% | Nivel de avance de la técnica |
**Etiquetas de puntuación:**
- **0**: Sin riesgos detectados
- **0.1-3**: Riesgo bajo (amenazas de una sola etapa, baja especificidad)
- **3.1-7.5**: Riesgo medio (cadena de ataque parcial, indicadores de metadatos o hallazgos de código de una sola etapa)
- **7.6-10**: Riesgo alto (cadena de ataque de múltiples etapas con evidencia en el código fuente — casi certeza de compromiso)
**Etapas de la cadena de ataque** (basadas en MITRE ATT&CK):
- **Temprana**: Acceso inicial, capacidades de ejecución
- **Media**: Persistencia, evasión de defensas, acceso a credenciales
- **Tardía**: Comando y control, exfiltración, impacto
---
### Consulta la nueva [integración](https://docs.datadoghq.com/integrations/guarddog/) del Datadog Agent y el [content pack](https://app.datadoghq.com/security/siem/content-packs?query=guarddog) de Cloud SIEM para GuardDog.
---
## Primeros pasos
### Instalación
La forma más sencilla de ejecutar GuardDog es usar [`uvx`](https://docs.astral.sh/uv/guides/tools/):
```sh
uvx guarddog pypi scan requests
```
Para instalarlo localmente:
```sh
uv tool install guarddog
# o
pip install guarddog
```
O usa la imagen de Docker:
```sh
docker pull ghcr.io/datadog/guarddog
alias guarddog='docker run --rm ghcr.io/datadog/guarddog'
```
*Nota: En Windows, el único método de instalación compatible es Docker.*
### Ejemplos de uso
```sh
# Escanea la versión más reciente del paquete 'requests'
guarddog pypi scan requests
# Escanea una versión específica del paquete 'requests'
guarddog pypi scan requests --version 2.28.1
# Escanea el paquete 'requests' usando 2 heurísticas específicas
guarddog pypi scan requests --rules exec-base64 --rules code-execution
# Escanea el paquete 'requests' usando todas las reglas excepto una
guarddog pypi scan requests --exclude-rules exec-base64
# Escanea un archivo de paquete local
guarddog pypi scan /tmp/triage.tar.gz
# Escanea un directorio de paquete local
guarddog pypi scan /tmp/triage/
# Escanea un paquete almacenado en S3 (una carpeta/prefijo o un único objeto de archivo)
guarddog pypi scan s3://my-bucket/path/to/package/
guarddog pypi scan s3://my-bucket/path/to/package.tar.gz
# Escanea cada paquete referenciado en un archivo requirements.txt de una carpeta local
guarddog pypi verify workspace/guarddog/requirements.txt
# Escanea cada paquete referenciado en un archivo requirements.txt y genera un archivo sarif - solo funciona con verify
guarddog pypi verify --output-format=sarif workspace/guarddog/requirements.txt
# Genera JSON en la salida estándar - funciona para todos los comandos
guarddog pypi scan requests --output-format=json
# Todos los comandos también funcionan con npm, go, crates, rubygems
guarddog npm scan express
guarddog go scan github.com/DataDog/dd-trace-go
guarddog go verify /tmp/repo/go.mod
# Escanea crates de Rust
guarddog crates scan serde
guarddog crates verify /tmp/repo/Cargo.lock
# Escanea paquetes RubyGems
guarddog rubygems scan rails
guarddog rubygems verify /tmp/repo/Gemfile.lock
# También puede escanear acciones de GitHub implementadas en JavaScript
guarddog github_action scan DataDog/synthetics-ci-github-action
guarddog github_action verify /tmp/repo/.github/workflows/main.yml
# Escanea extensiones de VSCode desde el marketplace
guarddog extension scan ms-python.python
# Escanea una versión específica de una extensión de VSCode
guarddog extension scan ms-python.python --version 2023.20.0
# Escanea un directorio de extensión de VSCode local o un archivo VSIX
guarddog extension scan /tmp/my-extension/
# Ejecuta en modo de depuración
guarddog --log-level debug npm scan express
```
## Escaneo en entorno aislado (sandbox)
Al escanear paquetes, GuardDog ejecuta el análisis del código fuente dentro de un **sandbox a nivel de kernel** (Linux mediante Landlock, macOS mediante Seatbelt, usando [nono](https://github.com/always-further/nono-py)). El sandbox bloquea todo el acceso a la red y restringe las operaciones del sistema de archivos solo a las rutas necesarias para el análisis. Esto protege contra paquetes maliciosos que intentan ejecutar código durante la extracción del archivo o el escaneo.
De forma predeterminada, el sandbox es obligatorio: si no está disponible en la plataforma, el escaneo falla en lugar de ejecutarse sin protección. Para escanear sin él, debes pasar explícitamente `--no-sandbox`:
```sh
# Predeterminado: requiere el sandbox, sale con un error si no está disponible
guarddog pypi scan requests
# Desactiva explícitamente el sandbox
guarddog pypi scan requests --no-sandbox
```
Para paquetes remotos, se ejecutan tres fases con diferentes niveles de privilegio:
1. La **descarga** y el **análisis de metadatos** se ejecutan sin sandbox (necesitan acceso a la red)
2. La **extracción del archivo** se ejecuta en un subproceso aislado (red bloqueada, sistema de archivos restringido)
3. El **análisis del código fuente** (YARA) se ejecuta en el proceso principal después de aplicar un sandbox (red bloqueada, sistema de archivos restringido a los archivos extraídos)
El sandbox se introdujo para mitigar las vulnerabilidades de path traversal y ejecución de código durante la extracción de archivos (CVE-2022-23530, CVE-2022-23531, CVE-2026-22870, CVE-2026-22871).
## Escaneo de paquetes desde S3
GuardDog puede escanear un paquete almacenado en S3, ya sea como carpeta/prefijo o como un único objeto de archivo:
```sh
guarddog npm scan s3://my-bucket/path/to/package/
guarddog npm scan s3://my-bucket/path/to/package.tar.gz
```
Esto utiliza tus credenciales AWS existentes (variables de entorno, `~/.aws`, SSO o un rol de IAM). GuardDog verifica la autenticación mediante STS antes de hacer nada y sale con un error si no se encuentran credenciales válidas. Los objetos se sincronizan a un directorio temporal, se escanean bajo el sandbox como cualquier otro contenido no confiable y se eliminan del disco después.
## Reglas
GuardDog utiliza dos tipos de reglas de detección, ambas participan en el motor de puntuación basado en riesgos:
* **Reglas de código fuente** (YARA): Análisis estático del código fuente del paquete que detecta capacidades y amenazas
* **Reglas de metadatos** (detectores de Python): Análisis de los metadatos del registro de paquetes que detecta indicadores de ataques a la cadena de suministro
Para la lista completa de reglas por ecosistema, consulta **[RULES.md](https://github.com/datadog/guarddog/blob/v3/RULES.md)**.
Para obtener orientación sobre cómo escribir nuevas reglas, consulta **[WRITING_RULES.md](https://github.com/datadog/guarddog/blob/v3/WRITING_RULES.md)**.
## Ejecutar GuardDog en una GitHub Action
La forma más sencilla de integrar GuardDog en tu pipeline de CI es aprovechar el formato de salida SARIF y subirlo a la función de [code scanning](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning) de GitHub.
Con esto, obtienes:
* Comentarios automáticos en tus pull requests basados en la salida del escaneo de GuardDog
* Gestión de falsos positivos integrada directamente en la interfaz de GitHub
Ejemplo de GitHub Action usando GuardDog:
```yaml
name: GuardDog
on:
push:
branches:
- main
pull_request:
branches:
- main
permissions:
contents: read
jobs:
guarddog:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
name: Scan dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v7
- run: uvx guarddog pypi verify requirements.txt --output-format sarif --exclude-rules repository_integrity_mismatch > guarddog.sarif
- name: Upload SARIF file to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
category: guarddog-builtin
sarif_file: guarddog.sarif
```
## Desarrollo
### Ejecutar una versión local de GuardDog
* Asegúrate de que poetry tenga un entorno con `python >=3.10` `poetry env use 3.10.0`
* Instala las dependencias `poetry install`
* Ejecuta guarddog `poetry run guarddog` o `poetry shell` y luego ejecuta `guarddog`
### Pruebas unitarias
Ejecutar todas las pruebas unitarias: `make test`
Ejecutar pruebas unitarias contra las heurísticas de metadatos de paquetes: `make test-metadata-rules` (las pruebas están [aquí](https://github.com/DataDog/guarddog/tree/v3/tests/analyzer/metadata)).
### Evaluación comparativa (benchmarking)
Puedes ejecutar GuardDog en paquetes legítimos y maliciosos para determinar falsos positivos y falsos negativos. Consulta [./tests/samples](https://github.com/datadog/guarddog/blob/v3/tests/samples)
### Controles de calidad del código
Ejecuta el verificador de tipos con
```shell
mypy --install-types --non-interactive guarddog
```
y el linter con
```shell
flake8 guarddog --count --select=E9,F63,F7,F82 --show-source --statistics --exclude tests/analyzer/sourcecode,tests/analyzer/metadata/resources,evaluator/data
flake8 guarddog --count --max-line-length=120 --statistics --exclude tests/analyzer/sourcecode,tests/analyzer/metadata/resources,evaluator/data --ignore=E203,W503
```
### Configuración mediante variables de entorno
El comportamiento de GuardDog se puede personalizar mediante variables de entorno:
#### Configuración general
| Variable de entorno | Descripción | Valor predeterminado |
|---------------------|-------------|---------------|
| `GUARDDOG_PARALLELISM` | Número de hilos a usar para el procesamiento en paralelo | Número de CPUs disponibles |
| `GUARDDOG_VERIFY_EXHAUSTIVE_DEPENDENCIES` | Analizar todas las versiones posibles de dependencias (`true`/`false`) | `false` |
| `GUARDDOG_NPM_INCLUDE_DEV_DEPENDENCIES` | Incluir `devDependencies` al escanear archivos `package.json` de npm (`true`/`false`); también se puede alternar por invocación con `guarddog npm verify --include-dev-dependencies` | `false` |
| `GUARDDOG_TOP_PACKAGES_CACHE_LOCATION` | Ubicación del directorio de caché de paquetes principales | `guarddog/analyzer/metadata/resources` |
| `GUARDDOG_YARA_EXT_EXCLUDE` | Lista separada por comas de extensiones de archivo a excluir del escaneo YARA | `ini,md,rst,txt,lock,json,yaml,yml,toml,xml,html,csv,sql,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,changelog,readme,makefile,dockerfile,pkg-info,d.ts` |
#### Configuración de reglas de metadatos
| Variable de entorno | Descripción | Valor predeterminado |
|---------------------|-------------|---------------|
| `GUARDDOG_NEW_DEPENDENCY_RISK_THRESHOLD` | Puntuación de riesgo mínima para que una dependencia recién introducida marque el paquete principal en la regla `risky_new_dependency` | `5.0` |
#### Límites de seguridad en la extracción de archivos
GuardDog implementa múltiples controles de seguridad al extraer archivos de paquetes para proteger contra bombas de compresión y ataques de agotamiento de descriptores de archivo:
| Variable de entorno | Descripción | Valor predeterminado |
|---------------------|-------------|---------------|
| `GUARDDOG_MAX_UNCOMPRESSED_SIZE` | Tamaño máximo permitido sin comprimir en bytes (evita el agotamiento del espacio en disco) | 2147483648 (2 GB) |
| `GUARDDOG_MAX_COMPRESSION_RATIO` | Relación de compresión máxima permitida (detecta patrones de compresión sospechosos) | 100 (100:1) |
| `GUARDDOG_MAX_FILE_COUNT` | Número máximo de archivos permitidos en un archivo (evita el agotamiento de descriptores de archivo/inodos) | 100000 |
## Mantenedores
* [Sebastian Obregoso](https://www.linkedin.com/in/sebastianobregoso/)
* [Ian Kretz](https://github.com/ikretz)
* [Tesnim Hamdouni](https://github.com/tesnim5hamdouni)
## Autores
* [Ellen Wang](https://www.linkedin.com/in/ellen-wang-4bb5961a0/)
* [Christophe Tafani-Dereeper](https://github.com/christophetd)
## Agradecimientos
Inspiración:
* [Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks](https://arxiv.org/pdf/2005.09535)
* [What are Weak Links in the npm Supply Chain?](https://arxiv.org/pdf/2112.10165.pdf)
* [A Survey on Common Threats in npm and PyPi Registries](https://arxiv.org/pdf/2108.09576.pdf)
* [A Benchmark Comparison of Python Malware Detection Approaches](https://arxiv.org/pdf/2209.13288.pdf)
* [Towards Measuring Supply Chain Attacks on Package Managers for Interpreted Languages](https://arxiv.org/pdf/2002.01139)