Metadata-Version: 2.4
Name: uv-audit2
Version: 0.2.0
Summary: A pip-audit like tool for auditing Python packages in requirements files.
Author-email: SpielerNogard <christophermueller2@outlook.de>
Requires-Python: >=3.13
Description-Content-Type: text/markdown
Requires-Dist: aiohttp>=3.8.0
Requires-Dist: typer==0.17.3
Requires-Dist: rich==14.1.0

# uv-audit
pip-audit like vulnerability scanning but fast

My example requirements.txt:
```
# This file was autogenerated by uv via the following command:
#    uv pip compile pyproject.toml -o runtime/requirements.txt
annotated-types==0.7.0
    # via pydantic
anyio==4.9.0
    # via starlette
cachetools==5.5.2
    # via google-auth
certifi==2025.4.26
    # via requests
charset-normalizer==3.4.2
    # via requests
click==8.2.1
    # via
    #   flask
    #   functions-framework
cloudevents==1.12.0
    # via functions-framework
deprecation==2.1.0
    # via cloudevents
fastapi==0.115.12
    # via availability-profile (pyproject.toml)
flask==2.2.5
    # via
    #   functions-framework
    #   vellox
functions-framework==3.8.3
    # via availability-profile (pyproject.toml)
google-api-core==2.25.0
    # via
    #   google-cloud-core
    #   google-cloud-firestore
google-auth==2.40.3
    # via
    #   google-api-core
    #   google-cloud-core
    #   google-cloud-firestore
google-cloud-core==2.4.3
    # via google-cloud-firestore
google-cloud-firestore==2.21.0
    # via availability-profile (pyproject.toml)
googleapis-common-protos==1.70.0
    # via
    #   google-api-core
    #   grpcio-status
grpcio==1.72.1
    # via
    #   google-api-core
    #   grpcio-status
grpcio-status==1.72.1
    # via google-api-core
gunicorn==23.0.0
    # via functions-framework
idna==3.10
    # via
    #   anyio
    #   requests
itsdangerous==2.2.0
    # via flask
jinja2==3.1.6
    # via flask
markupsafe==3.0.2
    # via
    #   jinja2
    #   werkzeug
packaging==25.0
    # via
    #   deprecation
    #   gunicorn
proto-plus==1.26.1
    # via
    #   google-api-core
    #   google-cloud-firestore
protobuf==6.31.1
    # via
    #   google-api-core
    #   google-cloud-firestore
    #   googleapis-common-protos
    #   grpcio-status
    #   proto-plus
pyasn1==0.6.1
    # via
    #   pyasn1-modules
    #   rsa
pyasn1-modules==0.4.2
    # via google-auth
pydantic==2.11.5
    # via fastapi
pydantic-core==2.33.2
    # via pydantic
requests==2.32.3
    # via google-api-core
rsa==4.9.1
    # via google-auth
sniffio==1.3.1
    # via anyio
starlette==0.46.2
    # via fastapi
typing-extensions==4.14.0
    # via
    #   fastapi
    #   pydantic
    #   pydantic-core
    #   typing-inspection
    #   vellox
typing-inspection==0.4.1
    # via pydantic
urllib3==2.4.0
    # via requests
vellox==0.1.3
    # via availability-profile (pyproject.toml)
watchdog==6.0.0
    # via functions-framework
werkzeug==3.1.3
    # via
    #   flask
    #   functions-framework
```

scanned once with `pip-audit`
![pip-audit](./docs/images/pip-audit.png)

and once with `uv-audit`
![uv-audit](./docs/images/uv-audit.png)

uv-audit needs 0.852s and pip-audit needs 4.617s total to scan the same requirements.txt file.
I expect the time to diverge even more with larger requirements files or when using multiple requirements files.

# Usage

Install:
```
uv pip install .
```

Audit a requirements file:
```
uv-audit -r requirements.txt
```

Audit a pyproject.toml (main dependencies only):
```
uv-audit -r pyproject.toml
```

Include specific dependency groups and/or extras:
```
uv-audit -r pyproject.toml --group dev --extra cli
```

Include everything (all groups + all extras):
```
uv-audit -r pyproject.toml --all
```

Shortcut for a project directory (uses its pyproject.toml):
```
uv-audit ./my-project --all-groups
```

Mix files in one run:
```
uv-audit -r requirements.txt -r ./svc/pyproject.toml --all-groups
```

## Machine-readable output

Use `--json` to emit results as JSON on stdout (errors go to stderr). The
payload lists every scanned input — including clean ones — along with the
resolved groups/extras selection.

```
uv-audit -r pyproject.toml --all --json
```

Example output:
```json
{
  "vulnerable": true,
  "inputs": [
    {
      "source": "/abs/path/to/pyproject.toml",
      "kind": "pyproject",
      "groups": ["dev"],
      "extras": ["cli"],
      "vulnerabilities": [
        {
          "package": "flask",
          "version": "1.1.2",
          "id": "GHSA-XYZ",
          "fix_versions": ["2.0.0"],
          "link": "https://example.com"
        }
      ]
    },
    {
      "source": "/abs/path/to/requirements.txt",
      "kind": "requirements",
      "groups": [],
      "extras": [],
      "vulnerabilities": []
    }
  ]
}
```

For requirements files the `groups` and `extras` arrays are always empty so
the shape is identical across input kinds. Exit code is non-zero when any
vulnerability is found.

Quick recipes with `jq`:
```
uv-audit -r pyproject.toml --all --json | jq '.vulnerable'
uv-audit -r pyproject.toml --all --json | jq '.inputs[] | select(.vulnerabilities | length > 0)'
uv-audit -r pyproject.toml --all --json | jq -r '.inputs[].vulnerabilities[].id'
```

## Install as a uv tool

From PyPI (package name is `uv-audit2`, CLI command stays `uv-audit`):
```
uv tool install uv-audit2
uv-audit -r requirements.txt
```

Or directly from git:
```
uv tool install git+https://github.com/SpielerNogard/uv-audit.git@main
uv tool run uv-audit -r requirements.txt
```

