Skip to content
Putting technology to work.
Insights to guide decisions and action.

Search articles

Continuously checking Python dependency vulnerabilities with uv audit: Institutionalizing vulnerability management for maintenance contracts

Table of contents · 6 items

"A critical vulnerability was discovered in a library used by the system delivered six months ago"—in custom development under maintenance contracts, such notifications arrive out of nowhere. The issue is whether we noticed it first. Scrambling to investigate after a client or news report flags it versus having already detected it via continuous CI checks makes a world of difference in client trust. Having a mechanism that continuously monitors Python projects for known vulnerabilities in dependencies directly determines maintenance quality.

As reported by gihyo.jp, the vulnerability scanning command uv audit has been added in preview to uv, which has gained widespread adoption as a high-speed package manager. What previously required separate tools like pip-audit can now be managed directly within uv alongside dependency management. In this article, we outline from an engineering perspective how to use uv audit to build a system that never misses dependency vulnerabilities during client maintenance, along with key operational considerations.

Why dependency vulnerability management ends up reactive

Lagging behind on dependency vulnerabilities usually happens because there is no automated system in place. It generally falls into three patterns.

First is not monitoring at all. Even if up to date upon delivery, libraries update continuously and vulnerabilities are published daily. If no one checks after delivery, dangerous conditions can persist unnoticed for months.

Second is manual checks becoming a mere formality. The operational rule of "verifying manually before release" gets skipped when workloads surge. Audits relying on human goodwill will inevitably fail.

Third is overlooking transitive dependencies. Vulnerabilities lurk not only in direct dependencies, but also in downstream dependencies pulled in by them. Unless the full lockfile is inspected, the true risk cannot be gauged.

uv audit addresses all three issues by programmatically and continuously scanning the entire dependency tree locked in the lockfile. The key advantage is running it as an automated CI job rather than relying on human memory. The importance of maintaining synchronized dependency versions was also covered in our article on eliminating dependency drift with monorepos. Vulnerability auditing serves as the next layer, monitoring whether those synchronized dependencies are secure.

uv audit fundamentals: Matching lockfiles against vulnerability databases

uv audit checks dependencies recorded in a project's lockfile (uv.lock) against known vulnerability databases and reports any matches. Crucially, it scans not only direct dependencies but the entire locked dependency tree.

# プロジェクトの依存に既知脆弱性がないかチェックする
uv audit

When a vulnerability is detected, the report details which package and version are affected, which vulnerability (such as a CVE) applies, and which version contains the fix. From there, the workflow simply entails upgrading the affected package to the patched version and updating the lockfile.

# 該当パッケージを修正版へ更新し、ロックを取り直す
uv lock --upgrade-package <パッケージ>

Because the command is in preview, options and output formats may evolve. When integrating it into production operations, pin the uv version and verify how output is parsed internally before putting it on automation pipelines.

Integrating into CI for client maintenance

The value of uv audit lies not in running it manually, but in running it automatically and periodically in CI. In client maintenance, standard practice involves running two distinct pipelines.

TriggerObjective
On every pull requestBlocks newly introduced dependencies from bringing in vulnerabilities prior to merging
Daily or weekly scheduled runsDetects newly disclosed vulnerabilities even when no code changes have occurred

The second pipeline is particularly vital. Vulnerabilities do not arise only when your code changes; they emerge when new vulnerabilities are disclosed to the public. Even if code has sat untouched for six months, its dependencies can become insecure in the interim. Scheduled runs are essential to catch when dependency risks change despite unchanged application code.

When integrating with GitHub Actions, a scheduled workflow looks like this:

# .github/workflows/audit.yml(抜粋)
on:
  schedule:
    - cron: '0 0 * * 1'   # 毎週月曜に実行
  pull_request:

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pipx install uv
      - run: uv audit

Unless you establish who handles detections and by what deadline, alerts will simply pile up. A practical approach is categorizing actions based on severity: automatically blocking PRs for critical flaws, while routing lower-severity notices to regular maintenance reviews. Just like auditing source code and secrets, detection mechanisms and operational flows must be designed together. This concept of not stopping at detection mirrors the principles discussed in our article on auditing sensitive information in source code.

Real-world systematization in client projects

An internal business system whose maintenance our company took over (keeping the company name confidential) had been running on Python for two years, and dependency vulnerability checks were performed manually only when a maintainer happened to remember before release. When we audited the project during handover, multiple libraries with known vulnerabilities that already had available patches were still in use. Because the application ran smoothly, no one had noticed the degradation of its dependencies.

Alongside migrating to uv, we incorporated uv audit into CI and configured two execution tracks: per-PR checks and weekly scheduled runs. We routed detections by severity: opening immediate update PRs for critical issues, while bundling minor fixes into monthly maintenance cycles. We simply replaced an informal, human-dependent habit with an automated weekly check. This systematically eliminated the risk of harboring dangerous dependencies unnoticed for months.

What proved most effective in this project was introducing scheduled runs. Per-PR checks can only catch newly introduced vulnerabilities. Risks in an existing live system can only be uncovered through scheduled scans—establishing both pipelines from the start directly established peace of mind in maintenance.

Where to begin

The starting point is checking whether the Python projects you currently maintain have a system for continuously checking dependency vulnerabilities. If not, run uv audit locally to assess current risks. From there, set up per-PR and scheduled checks in CI and define a response workflow (assignee and SLA) to transform vulnerability management from an occasional afterthought into an automated watch.

If you are falling behind on vulnerability response for delivered systems, looking to formalize dependency security under maintenance contracts, or aiming to embed security audits into CI, contact us through GleamHub's inquiry form. We will review your current project dependencies and CI pipelines to help build a maintenance structure that never misses a vulnerability.

Sources

Share this articleXFacebook
Kakeru Suzuki

Fascinated by the possibilities of technology, has had a deep interest in programming and digital art since student days

Turn this article's theme into your company's next step

Concrete steps forward for your organization.

We organize your desired architecture, legacy systems, and operational requirements to formulate your next steps toward execution.

  • Desired architecture
  • Integration with existing environments
  • Operational requirements
Consult on development & operations initiatives

You can consult with us from the initial conceptual stage. Details from this article will be carried over to the inquiry form.

Receive the latest articles by email