Safeguard
DevSecOps

Python Security Tools: The Ones Worth Running in Your Pipeline

A practitioner's tour of the Python security tools worth running: pip-audit for dependencies, Bandit for code, and detect-secrets, with CI examples.

Karan Patel
Platform Engineer
5 min read

The Python security tools worth running in almost every project are pip-audit for vulnerable dependencies, Bandit for insecure code patterns, and detect-secrets for leaked credentials — each covering a distinct risk class and each easy to wire into CI. You do not need a dozen tools; you need one from each category, gated properly, and the discipline to act on what they find.

This is a practitioner's shortlist, with the commands and the reasoning behind each pick.

pip-audit: known vulnerabilities in dependencies

Most of your security risk lives in packages you installed, many of them pulled in transitively. pip-audit, maintained under the Python Packaging Authority, checks your installed packages and requirements against the Python advisory database (PyPI's own vulnerability data plus OSV).

pip install pip-audit
pip-audit

To scan a requirements file specifically, or fail CI on findings:

pip-audit -r requirements.txt

pip-audit resolves the dependency tree, so it catches vulnerable transitive packages you never named directly. The workflow after a finding is standard: note the fixed version from the advisory, bump the dependency (directly or by constraining the transitive one), and re-run. For larger projects an SCA tool adds cross-ecosystem coverage and continuous monitoring for CVEs disclosed after you shipped, which pip-audit alone does not do.

A related habit: pin your dependencies. A requirements.txt with exact == versions, or a lockfile from Poetry/pip-tools, is what makes an audit meaningful — you cannot secure a dependency set that changes on every install.

Bandit: static analysis for insecure code patterns

pip-audit finds bugs you inherited; Bandit finds bugs you wrote. It is a SAST tool for Python that scans your source for common insecure patterns — use of assert for security checks, subprocess with shell=True, hardcoded passwords, weak hash functions, unsafe YAML loading, and eval on untrusted input.

pip install bandit
bandit -r your_package/

Bandit is opinionated and will flag things that are fine in context, so tune it. Suppress a specific false positive inline with a comment rather than lowering the whole ruleset:

subprocess.run(cmd, shell=True)  # nosec B602 - cmd is a fixed constant

Configure severity and confidence thresholds so the gate blocks on what matters:

bandit -r your_package/ -ll -ii

That runs at low-severity-and-above, medium-confidence-and-above. Start stricter in report-only mode, triage the backlog, then flip the gate on.

detect-secrets: keep credentials out of the repo

Hardcoded secrets are one of the most common and most damaging findings, because a leaked key in Git history stays exploitable until it is rotated. detect-secrets (from Yelp) scans for credential patterns and, importantly, maintains a baseline so you can adopt it on an existing repo without drowning in historical noise.

pip install detect-secrets
detect-secrets scan > .secrets.baseline

Then run it as a pre-commit hook so new secrets are caught at commit time, and audit the baseline periodically. Pair it with a policy that any exposed credential gets rotated, not just removed — deleting the line does not un-leak the key.

Safety and the dependency-scanning overlap

safety is another dependency scanner you will see referenced. It overlaps heavily with pip-audit; the practical difference is that pip-audit is PyPA-maintained and uses open advisory sources, while safety has a commercial database tier. Running one dependency scanner is enough — pick pip-audit for the open baseline unless you already have a reason to use safety.

Wiring them into CI

The value is in automation. A single job can run all three:

python-security:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-python@v5
      with:
        python-version: "3.12"
    - name: Install tools
      run: pip install pip-audit bandit detect-secrets
    - name: Dependency audit
      run: pip-audit -r requirements.txt
    - name: Static analysis
      run: bandit -r src/ -ll -ii
    - name: Secret scan
      run: detect-secrets scan --baseline .secrets.baseline

Order matters less here than gating: decide which findings fail the build (start with High-severity dependency CVEs and Bandit high-severity/high-confidence) and which merely report, so the gate stays trusted instead of bypassed.

What this stack does and does not cover

These three tools cover dependencies, code patterns, and secrets — the bulk of everyday Python risk. They do not cover runtime behavior. For that you add dynamic testing (DAST) against a running instance, which catches auth flaws and misconfiguration that static tools cannot see. And none of them replace a human review for logic flaws.

Start with pip-audit and detect-secrets because they are the highest value for the least tuning, then add Bandit once you have a triage habit. The Academy covers threshold tuning for each.

FAQ

What is the best Python dependency vulnerability scanner?

pip-audit, maintained by the Python Packaging Authority, is the strong open-source default. It checks installed packages and requirements against open advisory data (PyPI advisories and OSV) and resolves transitive dependencies. safety is a comparable alternative with a commercial database tier.

What does Bandit check for?

Bandit is a SAST tool that scans Python source for insecure patterns: shell=True in subprocess calls, hardcoded passwords, weak hashes, unsafe YAML loading, eval on untrusted input, and similar. Tune its severity and confidence thresholds and suppress false positives inline with # nosec.

How do I keep secrets out of my Python repo?

Use detect-secrets with a baseline to adopt it cleanly on an existing repo, run it as a pre-commit hook to catch new secrets, and rotate any credential that was ever committed — deleting the line does not undo the exposure.

Do I need both pip-audit and safety?

No. They overlap as dependency scanners. Run one; pip-audit is the open, PyPA-maintained baseline. Add a broader SCA tool if you need continuous monitoring and multi-ecosystem coverage.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.