Skip to main content

Scan your uv.lock file for dependencies with known vulnerabilities

Project description

uv-secure

Scan your uv.lock file for dependencies with known vulnerabilities.

Scope and Limitations

This tool will scan PyPi dependencies listed in your uv.lock files (or uv generated requirements.txt files) and check for known vulnerabilities listed against those packages and versions in the PyPi json API. Since it is making network requests for each PyPi package this can be a relatively slow tool to run, and it will only work in test environments with access to the PyPi API. Currently only packages sourced from PyPi are tested - there's no support for custom packages or packages stored in private PyPi servers. See roadmap below for my plans for future enhancements.

I don't intend uv-secure to ever create virtual environments or do dependency resolution - the plan is to leave that all to uv since it does that so well and just target lock files and fully pinned and dependency resolved requirements.txt files). If you want a tool that does dependency resolution on requirements.txt files for first order and unpinned dependencies I recommend using pip-audit instead.

Disclaimer

This tool is still in an alpha phase and although it's unlikely to lose functionality arguments may get changed with no deprecation warning. I'm still in the process of refining the command line arguments and configuration behaviour.

Installation

I recommend installing uv-secure as a uv tool or with pipx as it's intended to be used as a CLI tool, and it probably only makes sense to have one version installed globally.

Installing with uv tool as follows:

uv tool install uv-secure

or with pipx:

pipx install uv-secure

you can optionally install uv-secure as a development dependency in a virtual environment.

Usage

After installation, you can run uv-secure --help to see the options.

>> uv run src/uv_secure/run.py --help

 Usage: run.py [OPTIONS] [FILE_PATHS]...

 Parse uv.lock files, check vulnerabilities, and display summary.

╭─ Arguments ──────────────────────────────────────────────────────────────────────────╮
│   file_paths      [FILE_PATHS]...  Paths to the uv.lock or uv generated              │
│                                    requirements.txt files or a single project root   │
│                                    level directory (defaults to working directory if │
│                                    not set)                                          │
│                                    [default: None]                                   │
╰──────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ────────────────────────────────────────────────────────────────────────────╮
│ --aliases                           Flag whether to include vulnerability aliases in │
│                                     the vulnerabilities table                        │
│ --desc                              Flag whether to include vulnerability detailed   │
│                                     description in the vulnerabilities table         │
│ --ignore              -i      TEXT  Comma-separated list of vulnerability IDs to     │
│                                     ignore, e.g. VULN-123,VULN-456                   │
│                                     [default: None]                                  │
│ --config                      PATH  Optional path to a configuration file            │
│                                     (uv-secure.toml, .uv-secure.toml, or             │
│                                     pyproject.toml)                                  │
│                                     [default: None]                                  │
│ --version                           Show the application's version                   │
│ --install-completion                Install completion for the current shell.        │
│ --show-completion                   Show completion for the current shell, to copy   │
│                                     it or customize the installation.                │
│ --help                              Show this message and exit.                      │
╰──────────────────────────────────────────────────────────────────────────────────────╯
>> uv-secure
Checking dependencies for vulnerabilities...
╭───────────────────────────────╮
│ No vulnerabilities detected!  │
│ Checked: 160 dependencies     │
│ All dependencies appear safe! │
╰───────────────────────────────╯

Configuration

uv-secure can read configuration from a toml file specified with the config option. E.g.

uv-secure.toml / .uv-secure.toml

ignore_vulnerabilities = ["VULN-123"]
aliases = true
desc = true

pyproject.toml

[tool.uv-secure]
ignore_vulnerabilities = ["VULN-123"]
aliases = true
desc = true

Configuration discovery

If the ignore and config options are left unset uv-secure will search for configuration files above each uv.lock file and use the deepest found pyproject.toml, uv-secure.toml, or .uv-secure.toml for the configuration when processing that specific uv.lock file. uv-secure tries to follow Ruff's configuration file discovery strategy

Similar to Ruff, pyproject.toml files that don't contain uv-secure configuration are ignored. Currently if multiple uv-secure configuration files are defined in the same directory upstream from a uv.lock file the configurations are used in this precedence order:

  1. .uv-secure.toml
  2. uv-secure.toml
  3. pyproject.toml (assuming it contains uv-secure configuration)

So .uv-secure.toml files are used first, then uv-secure.toml files, and last pyproject.toml files with uv-secure config (only if you define all three in the same directory though - which would be a bit weird - I may make this a warning or error in future).

Like Ruff configuration files aren't hierarchically combined, just the nearest / highest precedence configuration is used. If you set a specific configuration file that will take precedence and hierarchical configuration file discovery is disabled. If you do specify a configuration options directly, e.g. pass the --ignore option that will overwrite the ignore_vulnerabilities setting of all found or manually specified configuration files.

Pre-commit Usage

uv-secure can be run as a pre-commit hook by adding this configuration to your .pre-commit-config.yaml file:

  - repo: https://github.com/owenlamont/uv-secure
    rev: 0.4.0
    hooks:
      - id: uv-secure

You should run:

pre-commit autoupdate

Or manually check the latest release and update the rev value accordingly.

Roadmap

Below are some ideas (in no particular order) I have for improving uv-secure:

  • Package for conda on conda-forge
  • Create contributor guide and coding standards doc
  • Add rate limiting on how hard the PyPi json API is hit to query package vulnerabilities (this hasn't been a problem yet, but I suspect may be for uv.lock files with many dependencies)
  • Explore some local caching for recording known vulnerabilities for specific package versions to speed up re-runs
  • Add support for other lock file formats beyond uv.lock
  • Consider adding support for scanning dependencies from the current venv
  • Add a severity threshold option for reporting vulnerabilities against
  • Add an autofix option for updating package versions with known vulnerabilities if there is a more recent fixed version
  • Investigate supporting private PyPi repos
  • Add translations to support languages beyond English (not sure of the merits of this given most vulnerability reports appear to be only in English but happy to take feedback on this)

Related Work and Motivation

I created this package as I wanted a dependency vulnerability scanner, but I wasn't completely happy with the options that were available. I use uv and wanted something that works with uv.lock files but neither of the main package options I found were as frictionless as I had hoped:

  • pip-audit uv-secure is very much based on doing the same vulnerability check that pip-audit does using PyPi's json API. pip-audit however only works with requirements.txt so to make it work with uv projects you need additional steps to convert your uv.lock file to a requirements.txt then you need to run pip-audit with the --no-deps and/or --no-pip options to stop pip-audit trying to create a virtual environment from the requirements.txt file. In short, you can use pip-audit instead of uv-secure albeit with a bit more friction for uv projects. I hope to add extra features beyond what pip-audit does or optimise things better (given the more specialised case of only needing to support uv.lock files) in the future.
  • safety also doesn't work with uv.lock file out of the box, it does apparently work statically without needing to build a virtual environment but it does require you to create an account on the safety site. They have some limited free account but require a paid account to use seriously. If you already have a safety account though there is a uv-audit package that wraps safety to support scanning uv.lock files.
  • Python Security PyCharm Plugin Lastly I was inspired by Anthony Shaw's Python Security plugin - which does CVE dependency scanning within PyCharm.

I build uv-secure because I wanted a CLI tool I could run with pre-commit. Statically analyse the uv.lock file without needing to create a virtual environment, and finally doesn't require you to create (and pay for) an account with any service.

Contributing

Please raise issues for any bugs you discover with uv-secure. If practical and not too sensitive sharing the problem uv.lock file would help me reproduce and fix these issues.

I welcome PRs for minor fixes and documentation tweaks. If you'd like to make more substantial contributions please reach out by email / social media / or raise an improvement issue to discuss first to make sure our plans are aligned before creating any large / time-expensive PRs.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uv_secure-0.5.0.tar.gz (47.8 kB view details)

Uploaded Source

Built Distribution

uv_secure-0.5.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file uv_secure-0.5.0.tar.gz.

File metadata

  • Download URL: uv_secure-0.5.0.tar.gz
  • Upload date:
  • Size: 47.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.5.17

File hashes

Hashes for uv_secure-0.5.0.tar.gz
Algorithm Hash digest
SHA256 56a425dd463124fa11da7ad61e4c25554f50ed4ba590ff20738849a613c587b9
MD5 1db4e91b09733cb4181088603697a466
BLAKE2b-256 89081894737bb45e13bfe4e0c05df31e61e561a250059880fef229a448ab1493

See more details on using hashes here.

File details

Details for the file uv_secure-0.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for uv_secure-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 01d4cc41f9ef3f8e7d799f56fb36641408464ce1d2e32cadf0bb7b10a8e8a171
MD5 0f4381606fa8936052acfff9bc1321bd
BLAKE2b-256 b6104adf805515e861477e737f4a72bb9717229d9d0c270006059cf1003a87d0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page