Skip to main content

Software Composition Risk Intelligence — score the real cost of updating a dependency

Project description

scori

Software Composition Risk IntelligenceKnow the cost before you update.

PyPI Python License CI

Free tools like pip-audit, OSV-Scanner, and Dependabot detect vulnerabilities and open update PRs — but none of them answer the question that matters: is it worth updating this lib right now, or does the migration cost outweigh the risk of not doing it? scori quantifies that friction as a single 0–100 score per dependency, using public data from PyPI, GitHub, and the OSV vulnerability database.

Install

pip install scori
# or
uv add scori

Usage

# Show friction scores for every dependency
scori friction --path .
scori friction --path . --format json > report.json
scori friction --path . --format html        # writes scori-report.html
scori friction --path . --ci                 # exit 1 if any score > 75
scori friction --path . --ci --threshold 50  # stricter gate

# Show only dependencies with updates available, sorted by friction
scori monitor --path .
scori monitor --path . --watch               # re-check every 5 minutes
scori monitor --path . --watch --interval 60 # re-check every 60 s

# Preview and apply dependency version updates
scori update --path . --dry-run              # show what would change
scori update --path . --apply                # write changes + create backup
scori update --path . --apply --max-friction medium  # only Low/Medium deps
scori update --path . --rollback             # restore from last backup

# List all detected dependencies
scori scan --path .

Example output (scori friction --format table, with color indicators):

                          scori — friction scores
┌───────────┬─────────┬─────────┬───────┬───────┬──────────┬─────────┐
│ Package   │ Current │ Latest  │ Jump  │ Score │ Label    │  CVEs   │
├───────────┼─────────┼─────────┼───────┼───────┼──────────┼─────────┤
│ django    │ 3.2.0   │ 5.1.0   │ major │  78   │ Critical │ 3 → 0 ✓ │
│ nltk      │ 3.8.1   │ 3.9.4   │ minor │  35   │ Medium   │ 9 → 0 ✓ │
│ requests  │ 2.31.0  │ 2.32.3  │ patch │   8   │ Low      │    —    │
└───────────┴─────────┴─────────┴───────┴───────┴──────────┴─────────┘

The CVEs column shows known vulnerabilities in your current version and whether they are fixed in the latest release:

  • 9 → 0 ✓ — 9 CVEs in current, all fixed in latest (prioritize this update)
  • 3 — 3 CVEs, still present in latest (update won't help with security)
  • — no known vulnerabilities in either version

scori monitor shows only the packages that have a newer release available, sorted by friction score (highest first), and marks with ★ any package where updating also fixes known CVEs.

How it works

The friction score is a weighted sum of five components (max 100):

Component Max weight Logic
Semantic version jump 50 patch=5, minor=25, major=50
Breaking signals in changelog 20 +4 per keyword found (max 20)
Affected transitive dependencies 15 +3 per transitive dep (max 15)
CVEs fixed by updating 15 +3 per fixed CVE (max 15)
Months without updating in project 10 +1 per month (max 10)
Current version yanked 5 +5 if yanked: true in PyPI API

Labels:

  • 0–25 → LowSafe to update
  • 26–50 → MediumUpdate with tests
  • 51–75 → HighUpdate in isolated branch
  • 76–100 → CriticalManual migration required

CVE data is fetched from the OSV database (free, no auth required). CVEs that are fixed by updating contribute up to +15 points to the friction score — a dependency where updating resolves known vulnerabilities will score higher, pushing it toward the top of your update queue. CVEs that remain present in the latest version do not affect the score (updating won't help with those).

Data sources

Source Data
https://pypi.org/pypi/{pkg}/json Latest version, release dates, yanked status
https://api.github.com/repos/{owner}/{repo}/releases Release notes for breaking signal detection
https://api.osv.dev/v1/query Known CVEs per version

Set GITHUB_TOKEN in your environment to raise the GitHub API rate limit from 60/h to 5000/h. PyPI and GitHub release data is cached in ~/.cache/scori/ for 1 hour. OSV results are cached in memory for the duration of a single run.

Version resolution

For pinned dependencies (fastapi==0.115.8), the pinned version is used directly. For unpinned dependencies (uvicorn with no version), scori looks up the installed version in the project's local venv (.venv/, venv/, or env/) before falling back to 0.0.0.

Roadmap

  • v0.2scori report: rich HTML with charts and history
  • v0.3 — support for poetry.lock and uv.lock for real transitive tree

Contributing

PRs and issues are welcome. Local setup:

git clone https://github.com/pauloestevao795/scori
cd scori
uv sync --group dev
uv run pre-commit install
uv run pytest

License

MIT

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

scori-0.1.0.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scori-0.1.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file scori-0.1.0.tar.gz.

File metadata

  • Download URL: scori-0.1.0.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for scori-0.1.0.tar.gz
Algorithm Hash digest
SHA256 97d807ad0364a4727c06f57dbcb8b0df990e567c829ad4670c50921afdacb1ba
MD5 1e8dd6a0bd4e953f744655568189bbbd
BLAKE2b-256 2af2d0c18a080659436986b04146357d5347356f91114546acb5472e6f492e74

See more details on using hashes here.

File details

Details for the file scori-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: scori-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for scori-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 08357691ba206853b6951ffeee8ba3a1cd42c0b73a406f1d1973e0c672131bc2
MD5 5551dbfdf3ee948cacce9bae9cfa1551
BLAKE2b-256 b445093c5a2d7e1b86d55e7d19fb72c3a5a24d4dca286556eb73e71cd6e1a9f9

See more details on using hashes here.

Supported by

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