Skip to main content

vendorcheck

CI License: MIT

Is the Python library bundled inside your app, add-on or extension byte-for-byte the official PyPI release?

Point it at a folder or an archive (.zip, .xpi, .vsix, .fda, .whl, any app bundle that is a zip). It finds the embedded Python packages, downloads the official release from PyPI, verifies the download against PyPI's published SHA-256, and compares file by file.

$ vendorcheck lib/ -v          # idna with one file edited and one file added
idna 3.7: 8 files identical, 1 modified, 1 extra.
    [modified] idna/core.py
    [extra] idna/evil.py

Real run on a clean pip install --target of yt-dlp:

$ vendorcheck lib/
yt_dlp 2026.8.19: 1049 files identical, 0 modified, 0 extra.

Why

Software supply-chain attacks often hide in copies of popular libraries: a vendored package that was quietly patched, or has an extra file dropped in. Lockfiles, pip-audit and signature checks look at what PyPI serves, not at the copy shipped inside your artifact. vendorcheck closes that gap.

Install

pip install git+https://github.com/Ferdi-krbk/vendorcheck
# or just download vendorcheck.py - it is a single file, stdlib only, Python 3.9+

Usage

vendorcheck PATH [-v | -vv] [--json] [--lang en|tr] [--only NAME ...] [--ignore GLOB ...]
                 [--no-nested] [--cache DIR] [--allow-empty]
Option Meaning
-v list every modified / extra / missing file
-vv additionally print a unified diff (official → embedded) for modified text files
--json machine-readable output (includes diffs with -vv)
--only NAME ... check just these packages
--ignore GLOB skip files matching the glob (relative to the package dir, e.g. yt_dlp/version.py); repeatable. For intentional local patches
--no-nested don't open archives found inside the input
--cache DIR reuse downloaded official releases
--allow-empty exit 0 if no embedded package is found (default: exit 2, so CI can't pass by checking nothing)
--lang tr Turkish output

Archives nested inside the input (.zip .whl .egg .xpi .vsix .fda .pyz, up to 2 levels, 2 GiB guard) are opened automatically and reported as pkg 1.0 [inner.xpi!/].

Exit codes: 0 identical · 1 differences found · 2 error / nothing checked.

In GitHub Actions the result is also written to the job's step summary as a table.

GitHub Action

- uses: actions/checkout@v4
- uses: Ferdi-krbk/vendorcheck@v1
  with:
    path: build/addon      # folder or .xpi/.vsix/.zip
    # only: "yt-dlp requests"

The job fails when embedded code differs from the official release. The repo's own CI proves it: a clean vendored tree must pass and a tampered one must fail.

How it works

  1. Detect packages through *.dist-info/METADATA, *.egg-info/PKG-INFO, or <pkg>/version.py (__version__ = "...").
  2. Fetch https://pypi.org/pypi/<name>/<version>/json, prefer a pure py3-none-any wheel, fall back to the sdist, and verify its SHA-256 against PyPI's digest.
  3. Compare each file's SHA-256. Line-ending-only differences (CRLF vs LF) are tolerated; __pycache__ and .pyc are ignored.
  4. Report identical / modified / extra (and missing) files.

Archives are extracted with zip-slip protection; nothing from the audited artifact is ever executed.

Limits (v1)

  • Only packages with version metadata (see above). Guessing name/version for bare copies is out of scope.
  • If PyPI only has platform wheels or an sdist, generated or compiled files show up as "extra".
  • Archives nested deeper than 2 levels are not opened.
  • It proves your copy equals what PyPI serves, not that the PyPI release itself is trustworthy. Pair it with pip-audit and provenance tools like trustcheck.
  • trustcheck verifies provenance/signatures of PyPI releases, not embedded code.
  • vendoring automates creating vendored trees; vendorcheck audits them.

License

MIT

Metadata

Release files for vendorcheck 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vendorcheck 0.2.0
File Size Uploaded
vendorcheck-0.2.0.tar.gz 10.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vendorcheck 0.2.0
File Interpreter ABI Platform
vendorcheck-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 22.2 kB

Release files / vendorcheck-0.2.0.tar.gz

Download URL vendorcheck-0.2.0.tar.gz
Size 10.8 kB
Tags Source
SHA-256 checksum
How to use checksums
a7b4aca4d6963c2dad55ac7ce519e8286c2eee6f9f845514ad705c837fcacc56
BLAKE2b-256 checksum
How to use checksums
82d7d8609b035f8409139c9dd0ea890c1e74e2116cdf897299c4f20b2e7529e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.0

Release files / vendorcheck-0.2.0-py3-none-any.whl

Download URL vendorcheck-0.2.0-py3-none-any.whl
Size 11.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
23d78a745d78f558b9603c7dde953ceb666e6f0105f1eee04d89042cb5503ab9
BLAKE2b-256 checksum
How to use checksums
2251a70d78bab72919d9f8fcca274e8a9514e3f5a1dfe2617ccef9b592607639
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.0

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page