Skip to content
StackPractices
beginner Por Mathias Paulenko

Escanear Paquetes Python en busca de CVEs Conocidos con

Cómo usar pip-audit para escanear dependencias Python en busca de vulnerabilidades conocidas, configurar ignore lists, integrar con CI/CD y remediar findings.

Temas: security

Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.

Overview

pip-audit es una herramienta para escanear dependencias de paquetes Python en busca de vulnerabilidades de seguridad conocidas. Consulta la PyPI Advisory Database (OSV) y reporta CVEs que afectan tus paquetes instalados. A diferencia de safety (que requiere una API key paga para coverage completo), pip-audit es gratis, open-source, y usa la base de datos OSV.dev mantenida por Google.

When to Use

  • Escanear proyectos Python en busca de dependencias vulnerables
  • Pipelines CI/CD para atrapar paquetes vulnerables antes del deployment
  • Security audits regulares de entornos de producción
  • Chequear si un upgrade de paquete introduce nuevas vulnerabilidades
  • Validar que una vulnerabilidad fue patcheada después de upgradear

When NOT to Use

  • Escanear source code en busca de patrones inseguros — usá Bandit en su lugar
  • Proyectos non-Python — pip-audit solo chequea paquetes Python
  • Cuando necesitás SCA (Software Composition Analysis) para licencias — usá pip-licenses
  • Para detección de vulnerabilidades en runtime — pip-audit es static, chequea versiones instaladas

Solution

Instalar pip-audit

pip install pip-audit

# Usando poetry
poetry add --group dev pip-audit

# Usando pipenv
pipenv install --dev pip-audit

# Usando uv
uv add --dev pip-audit

Scan básico

# Escanear el entorno actual
pip-audit

# Escanear un archivo requirements.txt
pip-audit -r requirements.txt

# Escanear múltiples requirements files
pip-audit -r requirements.txt -r requirements-dev.txt

# Output en formato JSON
pip-audit -f json -o audit-report.json

# Output en formato CSV
pip-audit -f csv -o audit-report.csv

# Output en Markdown
pip-audit -f markdown -o audit-report.md

Escanear con manifests de proyecto

# Escanear pyproject.toml (poetry/setuptools/hatch)
pip-audit --requirement pyproject.toml

# Escanear Pipfile.lock
pip-audit --requirement Pipfile.lock

# Escanear poetry.lock
pip-audit --requirement poetry.lock

# Escanear uv.lock
pip-audit --requirement uv.lock

Strict mode — fallar en cualquier vulnerabilidad

# Exit con non-zero code si se encuentran vulnerabilidades
pip-audit --strict

# Usar en CI/CD para fallar el build
pip-audit --strict -f json -o audit-report.json

Ignorar vulnerabilidades específicas

# Ignorar por CVE ID
pip-audit --ignore-vuln CVE-2023-12345

# Ignorar múltiples CVEs
pip-audit --ignore-vuln CVE-2023-12345 --ignore-vuln CVE-2023-67890

# Ignorar por GHSA (GitHub Security Advisory) ID
pip-audit --ignore-vuln GHSA-xxxx-xxxx-xxxx

Archivo de configuración

# pyproject.toml
[tool.pip-audit]
strict = true
requirement = ["requirements.txt"]
ignore-vuln = ["CVE-2023-12345", "GHSA-xxxx-xxxx-xxxx"]
output-format = "json"
output-file = "audit-report.json"

Fixear vulnerabilidades automáticamente

# Upgradear automáticamente paquetes vulnerables
pip-audit --fix

# Dry run — mostrar qué se upgradearía
pip-audit --fix --dry-run

# Fixear y escribir a requirements.txt
pip-audit --fix --require-hashes

Escanear con hash checking

# Verificar hashes de paquetes durante el scan
pip-audit --require-hashes -r requirements.txt

# Esto asegura que los paquetes no fueron tampered

Integración con CI/CD usando GitHub Actions

# .github/workflows/pip-audit.yml
name: pip-audit

on: [push, pull_request, schedule]
# Schedule: correr semanalmente para atrapar nuevos CVEs
on:
  push:
  pull_request:
  schedule:
    - cron: '0 6 * * 1'  # Todos los lunes 6 AM UTC

jobs:
  pip-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install pip-audit
        run: pip install pip-audit

      - name: Run pip-audit
        run: |
          pip-audit -r requirements.txt -f json -o audit-report.json || true

      - name: Check for HIGH severity vulnerabilities
        run: |
          HIGH_COUNT=$(python -c "
          import json
          with open('audit-report.json') as f:
              data = json.load(f)
          # Contar dependencias con vulnerabilidades
          count = sum(1 for dep in data.get('dependencies', []) if dep.get('vulns'))
          print(count)
          ")
          if [ "$HIGH_COUNT" -gt 0 ]; then
            echo "Found $HIGH_COUNT packages with vulnerabilities"
            cat audit-report.json
            exit 1
          fi

      - name: Upload report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: pip-audit-report
          path: audit-report.json

CI/CD con Poetry

# .github/workflows/pip-audit-poetry.yml
name: pip-audit (Poetry)

on: [push, pull_request]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install Poetry
        run: pip install poetry

      - name: Install dependencies
        run: poetry install --no-root

      - name: Run pip-audit
        run: |
          poetry run pip-audit --requirement poetry.lock --strict -f json -o audit-report.json

      - name: Upload report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: pip-audit-report
          path: audit-report.json

Pre-commit hook

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pypa/pip-audit
    rev: v2.7.3
    hooks:
      - id: pip-audit
        args: ["--strict", "--requirement", "requirements.txt"]
        files: ^requirements\.txt$

Integración con Makefile

# Makefile
.PHONY: audit
audit:
	pip-audit -r requirements.txt --strict -f json -o audit-report.json
	@echo "Audit complete. Report: audit-report.json"

.PHONY: audit-fix
audit-fix:
	pip-audit -r requirements.txt --fix --dry-run

.PHONY: audit-html
audit-html:
	pip-audit -r requirements.txt -f html -o audit-report.html

Workflow de remediación

# 1. Identificar paquetes vulnerables
pip-audit -r requirements.txt

# Output:
# Name    Version  Fix Versions  CVE ID          Description
# requests 2.28.0  2.31.0        CVE-2023-32681  Proxy-Authorization header leak

# 2. Chequear qué cambió en el fix
pip install requests==2.31.0 --dry-run

# 3. Upgradear el paquete vulnerable
pip install --upgrade requests==2.31.0

# 4. Actualizar requirements.txt
pip freeze | grep requests > requirements.txt

# 5. Re-escanear para verificar el fix
pip-audit -r requirements.txt

Usar pip-audit con constraints

# Escanear con constraints (e.g., Python version constraints)
pip-audit -r requirements.txt -c constraints.txt

# constraints.txt
# requests>=2.31.0
# urllib3>=2.0.0

Variants

pip-audit con Docker

# Dockerfile — escanear durante build
FROM python:3.12-slim AS audit

RUN pip install pip-audit
COPY requirements.txt .
RUN pip-audit -r requirements.txt --strict

FROM python:3.12-slim
COPY --from=audit /app /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "main.py"]

pip-audit con uv

# Instalar pip-audit con uv
uv add --dev pip-audit

# Escanear uv.lock
uv run pip-audit --requirement uv.lock --strict

# Escanear en CI
uv run pip-audit --requirement uv.lock -f json -o audit-report.json

pip-audit con Dependabot

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    # Dependabot abre PRs para paquetes desactualizados
    # pip-audit atrapa CVEs que Dependabot podría perder

Escanear virtual environments

# Escanear el virtual environment actual
source .venv/bin/activate
pip-audit

# Escanear un entorno específico
pip-audit --path /path/to/venv

# Escanear el system Python
pip-audit --system

Best Practices

  • For a deeper guide, see Find Security Issues in Python Code with Bandit.

  • Corré pip-audit en CI/CD en cada push — atrapá paquetes vulnerables early

  • Scheduleá scans semanales — nuevos CVEs se publican diariamente

  • Usá --strict en CI — fallá el build en cualquier vulnerabilidad

  • Documentá los CVEs ignorados — creá una política de ignore con fechas de expiración

  • Combiná con Bandit — pip-audit chequea dependencias, Bandit chequea código

  • Pineá versiones de paquetes — usá requirements.txt con versiones exactas, no ranges

  • Revisá los audit reports regularmente — no solo ignores y olvides

  • Usá --fix con precaución — upgradear paquetes puede introducir breaking changes

Common Mistakes

  • Ignorar todas las vulnerabilidades: usar --ignore-vuln para cada finding sin investigar. Algunos CVEs son críticos y necesitan atención inmediata.
  • No pinear versiones: escanear requirements no pineados (requests>=2.0) da resultados inexactos. Pineá versiones exactas.
  • Solo escanear requirements de producción: las dev dependencies también pueden tener vulnerabilidades. Escaneá ambas.
  • No schedulear scans regulares: correr pip-audit una vez no es suficiente. Nuevos CVEs se publican diariamente.
  • Upgradear sin testear: --fix upgradear paquetes automáticamente, lo que puede romper tu código. Siempre testeá después de upgradear.

FAQ

¿Qué es pip-audit?

Una herramienta que escanea dependencias de paquetes Python en busca de vulnerabilidades de seguridad conocidas usando la base de datos OSV.dev. Es gratis, open-source, y mantenida por la Python Packaging Authority (PyPA).

¿En qué se diferencia pip-audit de safety?

pip-audit es gratis y usa la base de datos OSV.dev. safety requiere una API key paga para coverage completo de vulnerabilidades. Ambos escanean dependencias Python, pero pip-audit es la opción gratis recomendada.

¿Qué base de datos usa pip-audit?

pip-audit usa la base de datos OSV.dev mantenida por Google, que agrega vulnerabilidades de PyPA Advisory Database, GitHub Security Advisories, y NVD.

¿Debería usar pip-audit o Dependabot?

Ambos. Dependabot abre PRs para upgradear paquetes desactualizados. pip-audit escanea en busca de CVEs conocidos y puede atrapar issues que Dependabot se pierde. Usalos juntos.

¿Puede pip-audit fixear vulnerabilidades automáticamente?

Sí, usá pip-audit --fix para upgradear automáticamente paquetes vulnerables. Usá --dry-run primero para ver qué cambiaría. Siempre testeá después de upgradear.