12.15 Issue 59 Vulnerability Ledger Refresh Design¶
Status: Approved by delegated recommendation on 2026-08-12
Issue: #59 — security: refresh the dependency vulnerability ledger
12.15.1 Decision¶
Refresh the human-reviewed vulnerability ledger from four explicit repository-controlled install surfaces. Keep the current accepted state, removed historical records, observation metadata, and revisit criteria in canonical Markdown. Do not add a checked-in audit JSON file, a live-audit CI job, advisory suppression, dependency upgrade, or machine-readable accepted baseline in this issue; Issue #60 owns that enforcement boundary.
This is a ledger-and-verification change, not a dependency change. It neither claims that an advisory disappeared because a package was remediated nor treats absence from one later feed snapshot as proof that the affected path is safe.
12.15.2 Context and observed drift¶
The existing §6.1.1 snapshot was recorded on 2026-07-04 from only
requirements.txt plus torch-requirements.txt. It reports 23 feed records across Torch,
PyTorch Lightning, and NLTK. A preliminary 2026-08-12 pip-audit 2.10.0 observation shows that
the aggregate runtime/Torch count remains 23 while the composition has changed:
torch==2.4.1: 22 feed records;pytorch-lightning==2.4.0: one feed record;nltk==3.9.4: no current record;- the locked documentation environment: no current record;
- the Atlas-contract test environment: no current record.
The preliminary run also exposed a command-shape constraint: auditing the universal hashed
docs-requirements.txt through pip resolution fails because an inactive universal dependency is
not present for the host interpreter while pip's hash mode still demands it. The documentation
lock must therefore be audited with --disable-pip, which consumes the complete pinned hash file
directly instead of re-resolving it.
These preliminary values must be reproduced with the final commands after the feature branch is created. They are design evidence, not a substitute for the final issue and PR evidence.
The identity delta is not equivalent to the primary-ID delta. Current feed aliases show that
former primary IDs CVE-2025-3000, CVE-2025-3730, and Lightning's
CVE-2026-31221 are now aliases of PYSEC-2025-194, PYSEC-2026-1970, and
PYSEC-2026-3043 respectively. They are re-keyed, not removed. PYSEC-2026-2286
(alias CVE-2026-24747) is a genuinely new identity that requires explicit review. NLTK's prior
record is absent because its open range now resolves to a newer version; that is resolver drift,
not a repository pin change or proof about every permissible resolution.
12.15.3 Alternatives considered¶
12.15.3.1 Recommended: current ledger plus explicit historical delta¶
Record one current four-surface snapshot and one historical-delta section. Scope the repository's static count verifier to the current section, so archived rows cannot inflate current totals. Keep raw JSON and resolver logs as temporary review evidence and summarize their exact commands, metadata, hashes, exits, and reconciliation in the issue and pull request.
This preserves human review, three-surface publication, and a clean handoff to Issue #60 without pretending the present Markdown is an automated gate.
12.15.3.2 Commit raw pip-audit JSON now¶
A committed raw snapshot would make evidence easier to diff, but it would introduce a de facto machine-readable baseline without defining update semantics, alias handling, version drift, or CI failure behavior. That is precisely Issue #60's scope, so this option is rejected.
12.15.3.3 Combine Issues #59 and #60¶
Implementing the refresh and enforcement together would reduce the number of integrations, but it would mix observation with policy, make review harder, and prevent Issue #60 from beginning from a reviewed accepted state. This option is rejected.
12.15.4 Audit surfaces and commands¶
All commands use python -m pip_audit, --strict, the PyPI vulnerability service, JSON output,
aliases enabled, descriptions disabled, and the progress spinner disabled. Exit 0 means a
complete audit with no findings; exit 1 means a complete audit with findings. Any other exit is
an invalid observation.
12.15.4.1 Runtime composition¶
python -m pip_audit \
-r requirements.txt -r torch-requirements.txt \
--strict --vulnerability-service pypi --format json \
--aliases on --desc off --progress-spinner off \
--output /tmp/ml-eng-lab-audit-runtime.json
The two manifests must be resolved together. requirements.txt contains ranged dependencies,
including torchao>=0.17; auditing it alone could resolve a Torch graph unlike the pinned local/CI
stack.
12.15.4.2 Torch attribution¶
python -m pip_audit \
-r torch-requirements.txt \
--strict --vulnerability-service pypi --format json \
--aliases on --desc off --progress-spinner off \
--output /tmp/ml-eng-lab-audit-torch.json
torch-requirements.txt includes torch-core-requirements.txt, so this isolates the complete
pinned Torch/PyG surface without constructing a second manifest interpretation.
12.15.4.3 Documentation lock¶
python -m pip_audit \
--disable-pip -r docs-requirements.txt \
--strict --vulnerability-service pypi --format json \
--aliases on --desc off --progress-spinner off \
--output /tmp/ml-eng-lab-audit-docs.json
docs-requirements.txt is already a complete universal hash lock. --disable-pip audits its
declared graph without host-specific re-resolution and avoids the observed hash-mode resolver
failure.
12.15.4.4 Atlas-contract test runner¶
python -m pip_audit \
-r atlas-contract-requirements.txt \
--strict --vulnerability-service pypi --format json \
--aliases on --desc off --progress-spinner off \
--output /tmp/ml-eng-lab-audit-atlas-contract.json
This manifest is not a transitive lock, so normal resolution remains intentional. It describes the focused repository-owned Atlas-policy test environment, not the Atlas submodule's images or service dependency surfaces.
12.15.5 Observation metadata and reconciliation¶
Each final result records:
- UTC observation timestamp;
- repository commit SHA;
- operating system, architecture, and Python version;
pip-auditversion and fixed vulnerability service;- exact input manifest paths and SHA-256 digests;
- exact command and exit status;
- resolved dependency count, affected-package count, and feed-record count;
- every emitted package, resolved version, primary advisory ID, aliases, and fix versions.
The unit of reconciliation is a feed record, not a deduplicated vulnerability event. If the feed emits the same primary ID twice, the ledger preserves a count of two and records the differing fix metadata where applicable. Aliases remain evidence attached to the record; they do not become additional current findings.
Every 2026-07-04 primary ID must be classified as retained, replaced by a newly emitted primary ID or alias, or absent from the current snapshot. An absent ID moves to the historical section with the statement that feed absence is not proof of remediation, non-reachability, or an upstream fix. Every new ID must receive an explicit accepted-risk rationale and revisit trigger before the ledger can be merged.
The reconciliation must report both raw feed-record count and unique advisory identity count. Raw-record totals remain the D10 integrity contract; unique identities plus aliases prevent a primary-ID rename from being misreported as one removed and one new vulnerability.
12.15.6 Canonical ledger structure¶
docs/dependency-contracts.md remains the sole canonical ledger and is projected to the generated
site and wiki by the existing manifest.
The audit snapshot will contain:
- a current observation-metadata block;
- a four-row install-surface result table;
- a current affected-package summary with declared constraint, audited version, feed-record count, accepted-risk rationale, and revisit trigger;
- a current advisory table retaining the parser-compatible leading columns
Package,Advisory ID,Feed Records, andFix Versions, followed by audited version and surface columns; - an alias-aware reconciliation table classifying every former and current identity as retained, re-keyed, absent, or genuinely new;
- a historical-delta table only for identities actually absent from the current feed;
- an explicit boundary stating that Issue #60 owns machine-readable enforcement and Issue #62 owns the coordinated Torch ecosystem upgrade.
The repository verifier must parse only the explicitly headed current snapshot. Historical rows must neither satisfy nor inflate current package and total counts. Missing or malformed current tables must continue to fail closed.
12.15.7 Security disposition¶
The current Torch and Lightning advisories remain accepted only as a bounded compatibility risk, not as ignored findings. The ledger must preserve these rules:
- never load untrusted Torch or Lightning checkpoints; pickle-backed artifacts can execute code;
- treat uncertain reachability as actionable uncertainty, not as absence of risk;
- do not upgrade one Torch ecosystem component in isolation;
- revisit immediately for a newly demonstrated reachable exploit, a compatible coordinated stack, an upstream fix that fits the full stack, or any dependency-pin change;
- otherwise revisit in Issues #61 and #62 as their NNx and Torch compatibility work proceeds.
No pip-audit --ignore-vuln, suppression file, or --fix operation is permitted in this issue.
No current root manifest uses a VCS, direct-reference, or editable requirement; if one is introduced
later, it requires an explicit audit treatment rather than silent reuse of this resolver contract.
12.15.8 Documentation surfaces¶
Required canonical changes are:
docs/dependency-contracts.md: current snapshot, historical delta, accepted-risk reasoning, and reproducible commands;SECURITY.md: preserve the precise manual-ledger versus automated-baseline boundary;CHANGELOG.md: record the dated four-surface refresh and the changed advisory composition;- this design, its implementation plan, and consecutive manifest entries 12.15–12.16.
README already points to the canonical ledger and should not duplicate transient counts. Generated site/wiki files remain ignored and must be regenerated only for validation.
12.15.9 Test and review strategy¶
Test-driven parser changes must prove:
- historical rows do not affect current D10 reconciliation;
- current package and total feed-record drift still fails;
- a missing or malformed current snapshot fails with a useful D10 finding;
- the real refreshed ledger passes;
- manifest entries 12.15 and 12.16 are consecutive and projected;
- generated site and wiki copies contain the same current snapshot marker and historical disclaimer.
Final verification includes all four audit commands, focused verifier/docs tests, full make test,
make verify, make lint, make docs-check, make docs-wiki, git diff --check, live feature and
release PR CI, and final GitFlow reconciliation. No Atlas, JupyterHub, Ollama, ComfyUI, container,
or other service is required or authorized.
12.15.10 Rollback and handoff¶
The change is independently reversible because it does not alter installed versions, workflow behavior, or service configuration. Reverting it restores the old ledger and its parser contract. Issue #60 must begin from the reviewed current table and define the checked-in schema, alias policy, version-drift behavior, update workflow, and CI failure semantics without reinterpreting this issue as an automated baseline.