Repository navigation
v0.12.0
Track T Phase 1: for PyPI and npm, MCP answers now carry checks on whether a dependency can be trusted, so an AI coding agent sees them before it adds or changes one.
- Registry digests: locked digests are compared with what the registry publishes.
- PyPI provenance: attestations are verified with the new optional
[provenance]extra. - Lookalike names: names that resemble popular packages are flagged as indicators.
- Added dependencies: a file check against an earlier copy checks only what was added or changed, and
openpulse trustdoes the same from the CLI. - Untrusted text: text from files and upstreams never reaches an agent unvalidated.
Every check uses the closed T-F1 status vocabulary and is never part of a verdict. Verdicts, contracts and the frozen evaluation are unchanged. No upgrade steps are needed. The new trust, provenance, lookalike and digest_integrity fields are additive.
Added
-
Trust checks on added dependencies (track T, v0.12.0 item U5).
check_dependency_filetakes an earlier copy of the file asbase_path; the PyPI and npm dependencies added or changed since then get registry existence, provenance (PyPI) and lookalike indicators in a newtrustblock. It holds counts per check and status, and lists everyCONFIRMED_MALICIOUS,VERIFIED_FAILUREorSUSPICIOUS_INCONCLUSIVErecord underattention.trust_allchecks every dependency instead. With neither,trustis null and nothing extra is fetched.- Budget: trust checks run before the file-wide lookups, so the additions get the session budget first. The live checks are capped at 40 packages per file (the W4 bound), and the rest are counted as capped. Lookalike is local data, so every package gets it.
- MCP:
base_pathis confined to the project root likepath. - CLI:
openpulse trust FILE [--base EARLIER] [--offline] [--json]prints the same block. It is report-only and never exits non-zero. - Never part of a verdict (tested). PyPI spelling variants (
Zope_Interface,zope.interface) are the same dependency, not an addition. - Not yet: the GitHub Action on pull requests. It needs the base file from git, and gating on trust statuses is T-E1 (track T Phase 4).
-
Lookalike-name indicators in
dependency_status(track T, T-A2, v0.12.0 item U4). A PyPI or npm name is compared with the curated catalog and a pinned popular-name list. Every rule that fires is named, with the reference it matched:separator: equal once-,_and.are removed;edit_distance: within 1 edit, or 2 for names of 10+ characters, where a swap counts as one;confusable: equal under the UTS #39 skeleton restricted to ASCII;scope: npm@x/namewherenameis a reference.- Outcomes:
SUSPICIOUS_INCONCLUSIVEis an indicator, never a typosquat verdict. A reference name isVERIFIED_RELATIONSHIP. Nothing firing isMISSING_EVIDENCE, not evidence of authenticity. Local data only: no network, no budget, never part of a verdict. - Reference data (owner-approved sources), each built and pinned by the new
scripts/refresh_reference_names.pyand listed in the newNOTICE:npm-high-impact1.13.0 (MIT, 17,335 names), checked against npm's sha512 integrity and read as text, never executed;- the ASCII mappings of UTS #39
confusables.txt18.0.0 (Unicode License v3), pinned by sha256.
- PyPI's popular list: a dated BigQuery query over the CC BY 4.0 download dataset, printed by the tool for a maintainer with a Google Cloud account to run. Until then, PyPI names are compared with the curated catalog only, and answers show the empty list.
-
PyPI provenance in
dependency_status(track T, T-B1, v0.12.0 item U3). For a PyPI package with a version, the newprovenancefield verifies the release's PEP 740 attestations from PyPI's Integrity API, for up to 4 files (wheels first), each against the file's sha256. Verification usespypi-attestations(Sigstore), never cryptography of our own.- Repository cross-check: for curated packages, the attestation's publisher is compared with the catalog's GitHub repository; a different repository is
VERIFIED_FAILURE(starjacking). - Other outcomes: an attestation that doesn't verify is
VERIFIED_FAILURE. No published provenance isMISSING_EVIDENCE, never a failure, because most packages publish none.VERIFIED_RELATIONSHIPsays where and how the files were built, never that they are benign (Ultralytics' first malicious releases carried valid provenance). - Untrusted text: publisher fields and file names are validated before they appear or reach a URL.
- New optional extra
[provenance](owner-approved, Phase 0 decision 5), Python 3.11+:pypi-attestationsand its ~24 dependencies, hash-locked in the newrequirements-provenance.lock, whichscripts/compile_locks.pygenerates, constrained to the core, mcp and audit-tool pins. Without the extra, the field isNOT_PERFORMEDwith how to enable it. A new CIprovenancejob installs it from the lock, checks drift, audits it and runs its tests. - Lock checker fixes:
scripts/check_lock.pynow reads the provenance lock and parses>=floors that carry an environment marker. - Unchanged: verdicts.
- Repository cross-check: for curated packages, the attestation's publisher is compared with the catalog's GitHub repository; a different repository is
-
Digest integrity for lockfiles (track T, T-B4, v0.12.0 item U2).
check_dependency_file(MCP) compares each digest apackage-lock.json(integrity) orpoetry.lock(files[].hash) pins with what npm (dist.integrity, ordist.shasumfor old sha1 locks) or PyPI (urls[].digests.sha256) publishes for that version. A locked digest the registry doesn't publish isVERIFIED_FAILURE, listed underdigest_integrity.failures: the locked artifact is not the one the registry serves (substituted, re-uploaded or tampered).- Other outcomes: no usable locked digest is
MISSING_EVIDENCE, and no usable registry answer isNOT_PERFORMED, never a failure. - Safety: lockfile digests are validated before use, and names before any URL. Each check spends one lookup from the session budget, under the 40-per-file cap.
- Reader output unchanged:
core.lockfile_reader.lockfile_digestsreads the digests separately, so the dependency entries the verdict engine, contracts and ledger use are untouched. - Unchanged: verdicts. No new dependency; hashing only.
- Other outcomes: no usable locked digest is
Security
- Reader skip messages never carry file text to an agent (track T, T-F3, v0.12.0 item U1).
check_dependency_file(MCP) passed the readers' skip messages through as written. Those messages quote the file's own lines, and the agent writes the files it asks about. A quoted value is now shown only when it has a requirement shape (requests>=2.31.0,junit:junit,^4.2: no whitespace, no Markdown link). Any other value becomes<not shown>, and messages are stripped of control, bidi and zero-width characters and capped at 240 characters. The CLI keeps the full messages for humans, stripped of control and bidi characters.