Webhook icon
Schedule icon
WorkingDirectory icon
Commands icon
Docker icon
Script icon
If icon
SlackIncomingWebhook icon
Fail icon
Log icon

Gate Python Releases on Known Dependency CVEs with pip-audit

Audit locked Python dependencies with pip-audit, count HIGH and CRITICAL advisories against your budget, and block the release with a Slack alert.

Categories
Infrastructure

How it works

  1. on_release_request (io.kestra.plugin.core.trigger.Webhook, keyed) accepts the release audit request from your deploy pipeline. nightly_audit (io.kestra.plugin.core.trigger.Schedule) ships disabled: true as a fallback net once an operator switches it on.
  2. audit_workspace (io.kestra.plugin.core.flow.WorkingDirectory) opens one shared filesystem so the locked pins, the report, and the grader all see the same files.
  3. run_pip_audit (io.kestra.plugin.scripts.shell.Commands on the io.kestra.plugin.scripts.runner.docker.Docker runner, image pyupio/pip-audit:latest) writes a pinned requirements.txt and a bundled fixture report with heredocs, then runs pip-audit -f json -r requirements.txt --progress-spinner off > pip-audit-report.json || true. When no index is reachable the empty redirect is replaced by the fixture, so the gate behaves the same offline and online.
  4. parse_report (io.kestra.plugin.scripts.python.Script on python:3.12-slim) counts advisories by severity, drops every id present in cve_allowlist, and emits the block decision, the counts, and the human summary through the outputs protocol.
  5. check_verdict (io.kestra.plugin.core.flow.If) branches on blocked. Over budget, notify_block posts the CVE summary to Slack and fail_release (io.kestra.plugin.core.execution.Fail) turns the execution red so the deploy pipeline stops. Within budget, log_pass records the all-clear.
  6. The errors block alerts Slack whenever the audit itself breaks, because a dead scanner looks exactly like a clean lockfile.

What you get

  • A release gate that fails a deploy when the locked pins carry known HIGH or CRITICAL advisories above your budget.
  • Allowlist support, so an advisory accepted by security review stops counting without editing the lockfile.
  • Deterministic behavior offline, the bundled fixture report exercises the same parser path a live scan does.
  • Gateable outputs, verdict, cve_count, high_count, cve_ids, and dependencies_checked for any parent release flow.
  • A dated execution history that doubles as evidence the dependency audit ran for that exact release.

Who it's for

  • Platform teams that want a CVE gate on Python releases without standing up a SaaS scanner.
  • Release engineers who need the audit to run the same way on a laptop, in CI, and on the release worker.
  • Security reviewers who want an allowlist that keeps accepted advisories visible but non-blocking.

Why orchestrate this with Kestra

pip-audit is one command, but a gate needs the state around it, a trigger from the deploy pipeline, a hermetic tool version pinned in the flow file, a budget decision that separates escalation from the all-clear, and an execution record proving the audit ran for that exact release. Kestra supplies all of that declaratively, with Slack routing and a failed execution that any pipeline already knows how to read. A make target running pip-audit gives you none of that, it only protects the releases of people who remember to run it.

Prerequisites

  • A worker with Docker access, both the audit and the grader run in containers.
  • A Slack incoming webhook for block notices and for failure alerts.
  • A deploy pipeline able to POST to the keyed webhook URL and to wait on the execution result.

Secrets

  • PIP_AUDIT_WEBHOOK_KEY: key segment guarding the webhook URL, anyone holding it can trigger an audit.
  • SLACK_WEBHOOK_URL: Slack incoming webhook URL.
  • PIP_INDEX_URL: optional, define it and pass it as an env var on run_pip_audit when your pins resolve from a private package index.

Quick start

  1. Add the secrets above to your Kestra namespace.
  2. Run the flow once with the default inputs and confirm the bundled fixture produces verdict, cve_count, and high_count in the outputs.
  3. Raise max_high_cves or add ids to cve_allowlist to model an accepted advisory, then re-run and watch the verdict flip to PASS.
  4. Point your deploy pipeline at /api/v1/{tenant}/executions/webhook/{namespace}/pip-audit-dependency-cve-gate/{PIP_AUDIT_WEBHOOK_KEY} once service_name is mapped from the POST body.

How to extend

  • Audit many services by wrapping this flow in a parent that calls it with a Subflow per service and aggregates the verdicts.
  • Swap the heredoc pins for a io.kestra.plugin.git.Clone of the real repository and audit the committed lockfile instead.
  • Open a Jira or GitHub ticket per blocking advisory with the matching plugin task under check_verdict.
  • Archive pip-audit-report.json to object storage with io.kestra.plugin.aws.s3.Upload so every release keeps its exact audit artifact.
  • Tighten or relax the budget per environment by overriding max_high_cves per caller, staging can tolerate more than production.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.