security Advanced

Supply Chain Security

One wheel, 5,098 hash-listed files, enforced integrity checks at import — and a manifest signature not yet active. The honest supply-chain inventory.

Published Feb 16, 2026

The supply-chain story of pyvorin-native 1.0.9 is unusually short: one wheel, installed by your package manager, containing everything the package will ever execute, with no second download stage anywhere in the product. That shape — a single, self-contained artefact — removes whole categories of supply-chain risk before any control is even discussed. This page inventories what ships, what verifies it, where verification currently stops, and which claims from earlier drafts did not survive contact with the artefact.

One artefact, nothing fetched later

The wheel pyvorin_native-1.0.9-cp312-cp312-linux_x86_64.whl is the entire delivery. A full sweep of every installed binary for URLs finds exactly three hosts embedded in the code — api.pyvorin.com, app.pyvorin.com, and localhost — and none of them serves components. There is no protected-component downloader, no per-module fetch, no "premium" second stage. Whatever supply-chain guarantees you establish at install time are the guarantees that apply for the package's whole life, because nothing else ever enters it.

What the wheel contains, per its manifest: 5,098 hash-listed files, almost all Cython-compiled shared objects built for cpython-312 on linux x86_64, plus the plain-Python glue between them. Package metadata declares the MIT licence and five runtime dependencies — pydantic, llvmlite, numpy, msgpack, and pynacl, the last of which performs the Ed25519 signature work for licence leases.

The inventory is the SBOM

Every file in the package appears in MANIFEST.json with its SHA256, alongside the version, build timestamp and a build watermark baked identically into the compiled modules and the generated integrity data. That manifest is, functionally, a software bill of materials: a complete, machine-readable list of what the build produced, with per-file hashes suitable for diffing between versions. Extracting it needs nothing but the package itself:

python -c "import json, pathlib; m = json.loads((pathlib.Path(pyvorin.__file__).parent / 'MANIFEST.json').read_text()); print(m['version'], len(m['files']))"
# On 1.0.9: 1.0.9 5098

Whether you feed that into a formal SBOM pipeline or just archive it beside each install, it gives you a per-file baseline to compare against after upgrades and a concrete answer to "what exactly changed between these two builds" — the two questions an SBOM exists to answer.

The check that runs: SHA256 against a baked-in table

Every process that imports pyvorin runs the integrity pass once, before any gated work: SHA256 of every compiled .so against EXPECTED_HASHES, a table baked into a generated file that carries the same build watermark as everything else in the 1.0.9 build. Cost: about five milliseconds. A mismatch raises a RuntimeError naming tampering, and the import fails closed — no warning you can scroll past, no setting that softens it into a log line. The only bypass is PYVORIN_DEV_MODE=1, an escape hatch for working on the source tree; its presence in a production environment is itself the kind of finding worth a ticket.

Understand the threat model precisely, because it has an edge. The hash table is a plain-text file inside site-packages. The check detects any modification of the binaries by anyone who did not also modify the table — complete against accidental corruption, clumsy "optimisation", and low-effort tampering. An attacker with write access to the install tree who edits both a .so and its listed hash passes the check. That edge is not a secret and it is not waved through: it is exactly the scenario the manifest signature was designed to close, which is the next section.

The gap, stated with its reproducing command

The build defines three Ed25519 verification keys. One is set and enforced: the lease key, which verifies server-signed licence leases, its secret existing only on the entitlement server. The other two ship empty in 1.0.9 — the manifest key and the entitlement-cache key — so both Ed25519 paths return early and are skipped in production. The manifest's own signature and public_key fields are empty strings. Confirm on any installed copy:

python -c "import pyvorin._signing_keys as k; print(repr(k.MANIFEST_PUBLIC_KEY), repr(k.CACHE_VERIFY_KEY))"
# On 1.0.9: '' ''

The consequence, without inflation: today, the package can verify that its binaries match its hash table, but cannot verify that its hash table is the one the build produced. Until a release ships a non-empty MANIFEST_PUBLIC_KEY, the correct compensating control is the one you already own — pin the wheel's hash at install time and monitor the install tree with your standard file-integrity tooling. The checkable part of that advice is the pinning: your package manager or an SBOM tool can record and verify the wheel hash today, at the artefact boundary, where a single-file package is easiest to defend.

The dependency surface

Five declared runtime dependencies is a genuinely small list for a package of this size, and each earns its place: pydantic for configuration models, llvmlite as the LLVM binding the compiler lowers through, numpy for numerical kernels, msgpack for the entitlement cache serialisation, and pynacl for Ed25519 verification. The supply-chain exposure they create is the ordinary pip exposure — resolved from your index, over your TLS, under your pinning policy — which is why the strongest single control for this package costs one line: install with hashes pinned and an index you control. Nothing in the package subverts or bypasses that pipeline; it simply rides it.

What earlier drafts claimed, and what happened to it

Three statements circulated in older material and are corrected here rather than repeated. "Compiled artifacts are signed with Ed25519; verify before loading with pyvorin verify artifact.so" — no such command exists in either CLI, and per-artifact Ed25519 verification is precisely the inactive path described above; what runs at load time is the SHA256 table check. "Same source plus same compiler equals identical artefact hash" — reproducible builds were not verified for 1.0.9 and we do not assert them. "Dependencies are scanned for CVEs before every release" — we hold no evidence of a systematic scanning process and will not claim one; the verifiable dependency fact is the short, declared list of five packages above, which is short enough to assess directly.

The pattern across those corrections is deliberate: a supply-chain page that overstates its controls is worse than none, because your reviewer will check, and the checkable version of this page is stronger than the inflated one. An engineer auditing this package gets a one-artifact delivery, a per-file hash inventory they can diff themselves, a runtime-enforced integrity check, a five-package dependency list, and one named gap with a reproducing command. That is a defensible position, and it ages well: every control on the list is either enforced at runtime today or checkable by you in seconds. A badge-shaped fiction is not, because it ages the moment a reviewer opens a terminal.

Deployment recommendations

In order of effort. Pin the wheel hash at install and record it in your SBOM alongside the manifest extract. Monitor the install tree — including the hash-table file itself — with the file-integrity tooling you run for every security-sensitive deployment, which closes the table-editing scenario until the manifest key ships. Verify the gap's status after every upgrade with the one-liner above; the day it prints a real key instead of two empty strings, the manifest path upgrades from documented gap to active control without any change on your side. And keep the manifest diff in your change records: with a per-file hash inventory, "what changed in this upgrade" is a thirty-second question with a definitive answer.

Where to go next

Last reviewed 13 February 2026 against pyvorin-native 1.0.9 installed at /root/pvfinal: manifest parsed from the installed wheel (5,098 files), _signing_keys.py read directly from the package, URL sweep of installed binaries, integrity table generation timestamp cross-checked against the build watermark. Claims of reproducible builds and release-time CVE scanning remain unverified and unclaimed.