The go-to resource for upgrading Python, Django, Flask, and your dependencies.

Running pip-audit in CI/CD: Failing Builds on Critical and High Severity Vulnerabilities


Unpinned dependencies can introduce vulnerabilities that reach production through requirements.txt. We’ll use pip-audit in CI/CD to scan locked files like requirements.txt or pyproject.toml, failing builds only for critical and high severity issues (CVSS 7.0+). Filter noise from low/medium vulns with JSON + jq or ignores—no manual scans needed. Includes GitHub Actions, GitLab CI, and Jenkins examples. Builds on article 16: Pinning Transitives.

Why pip-audit in CI/CD?

  • Automatic scanning: Checks locked dependencies (pinned via pip-compile or uv, as in article 16), exits non-zero on detected vulnerabilities.
  • Severity focus: Defaults to failing on any vulnerability; customize scripts parse JSON for critical/high only via description keywords or CVSS scores—though keyword matching can have limitations.
  • Performance: Typically fast (<1s for 100+ deps) by reusing pip cache; scales well for most projects.
  • Compliance: Audit logs support SOC2/PCI requirements, though consult your compliance team for full integration.

Of course, this requires pinned dependencies first (see article 16).

Test Locally First

# Install pip-audit (isolated, no deps conflicts)\n$ pipx install pip-audit\n\n# Test requirements.txt (assumes pinned from article 16)\n$ pip-audit -r requirements.txt  # Exits 1 on vulns\n\n# JSON output for severity filtering\n$ pip-audit -r requirements.txt --format=json

It exits non-zero on vulnerabilities, integrating seamlessly with CI && chains.

GitHub Actions Example

Full workflow—fails build if critical/high detected.

name: Python Security Audit (pip-audit)\non:\n  push:\n    paths: ['requirements.in', 'pyproject.toml', '**/*.txt']\n  pull_request:\n\njobs:\n  audit:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout code\n      uses: actions/checkout@v4
    - name: Set up Python 3.12\n      uses: actions/setup-python@v5\n      with:\n        python-version: '3.12'\n    - name: Install tools\n      run: pipx install pip-audit uv\n    - name: Compile pinned requirements (from article 16)\n      run: uv pip compile requirements.in -o requirements.txt --hashes
    - run: |
        pip-audit -r requirements.txt --format=json > audit.json
        # Fail only critical/high (grep CVSS keywords in desc; customize)
        # Fail only critical/high via keywords in description (approximate; tune regex for your vulns)\n        # Matches: "critical", "high", "CVSS [7-9]", "CVSS 10", case-insensitive\n        if jq -e '.[] | .vulns[] | select(.description | ascii_downcase | test("critical|high|cvss [7-9]|cvss 10|severity: high"; "i"))' audit.json > /dev/null; then\n          echo "Critical or high severity vulnerabilities found. Review audit.json."\n          exit 1
        fi
      name: pip-audit (critical/high only)
    - name: Fallback: Official pip-audit action (fails all vulns)\n      if: failure()\n      uses: pypa/gh-action-pip-audit@v1

Official gh-action-pip-audit: fails any vuln.

GitLab CI: .gitlab-ci.yml

audit:\n  stage: test\n  image: python:3.12-slim\n  script:\n    - name: Install pip-tools and pip-audit\n      pip install pip-tools pip-audit
    - name: Compile pinned requirements\n      pip-compile requirements.in --generate-hashes\n    - name: Run pip-audit JSON\n      pip-audit -r requirements.txt --format=json > audit.json || true\n    - name: Check for critical/high vulns (keyword approx)\n      |\n        if grep -qiE "critical|high severity|CVSS [7-9]|CVSS 10" audit.json; then
        echo "Critical/High vulns! Failing build."
        exit 1
      fi
  rules:
    - changes:
      - requirements.in
      - pyproject.toml

Jenkins Pipeline

pipeline {\n  agent any\n  stages {\n    stage('Python Security Audit') {\n      steps {\n        sh '''\n          # Install tools (pipx preferred, but pipx may need setup in agent)
          pipx install pip-audit\n          pip-audit -r requirements.txt --format=json > audit.json\n          # Fail on critical/high keywords (tune as needed)\n          if grep -qiE "critical|high severity|CVSS [7-9]|CVSS 10" audit.json; then
            echo "Failing: critical/high vulns"
            exit 1
          fi
        '''
      }
    }
  }
}

Ignore Low/Medium Vulns

> Tip: pip-audit draws from PyPA advisory database. For acceptable risks or false positives (e.g., resolved pytest issues), use --ignore-vuln ID.\n\nbash\n$ pip-audit -r requirements.txt --ignore-vuln GHSA-w596-4wvx-j9j6\n\n\nGenerate ignore file (review candidates):\n\nbash\n$ pip-audit -r requirements.txt --format=json | jq -r '.[]?.vulns?[]?.id // empty' | sort -u &gt; candidate-ignores.txt\n# Edit/review, rename to .pip-audit-ignores.txt, commit with comments\n\n\nLoad in CI: --ignore-vuln-file .pip-audit-ignores.txt

Commit .pip-audit-ignores.txt:

GHSA-w596-4wvx-j9j6  # pytest noise
PYSEC-2023-123  # Low impact

Load: pip-audit -r requirements.txt --ignore-vuln-file .pip-audit-ignores.txt

Troubleshooting

IssueFix
No vulns but failsUnpinned deps—pin via 16
jq/grep false posCustomize regex; use full OSV API for CVSS
Slow audits--no-deps + pinned/hashed reqs
Third-party index--index-url / --extra-index-url
Ignore not workingUse aliases CVE/GHSA

Alternative: Safety CLI\n\nSafety provides native severity-based failing:\n\nbash\n$ safety check --full-report -r requirements.txt --fail-on=CRITICAL,HIGH\n\n\nPros: Built-in CVSS parsing (no scripts), enterprise dashboards (Safety Pro).\nCons: Core free, advanced features paid; pip-audit is FOSS with PyPA backing.\n\nUse Safety if you need precise severity without custom logic; pip-audit for open-source simplicity.

Conclusion

With pip-audit and severity filtering, you can effectively gate critical and high vulnerabilities in your Python CI/CD pipelines while managing noise through ignores. Of course, regularly review and update your ignore list. For reproducible environments, see article 15 on uv/pip-sync.

Related:

Questions? Drop your CI yaml below.

Sponsored by Durable Programming

Need help maintaining or upgrading your Python application? Durable Programming specializes in keeping Python apps secure, performant, and up-to-date.

Hire Durable Programming