fix(assessment): keep release origin unproven
Some checks failed
Dependency Audit / dependency-audit (push) Failing after 15s
Security Audit / security-audit (push) Failing after 14s

This commit is contained in:
2026-07-22 19:55:35 +02:00
parent 4c16069f88
commit ddee5c00dc
6 changed files with 689 additions and 121 deletions

View File

@@ -3,12 +3,14 @@
from __future__ import annotations
import base64
import csv
from dataclasses import dataclass
from datetime import UTC, datetime, timedelta
import hashlib
import hmac
from importlib import metadata
from importlib.util import source_from_cache
import io
import json
import os
from pathlib import Path, PurePosixPath
@@ -27,6 +29,8 @@ from jsonschema.exceptions import SchemaError
MAX_GOVOPLAN_DISTRIBUTIONS = 256
MAX_DISTRIBUTION_FILES = 10_000
MAX_COLLECTION_RECORD_FILES = 50_000
MAX_RECORD_BYTES = 4 * 1024 * 1024
MAX_RECORD_PATH_CHARACTERS = 4096
MAX_HASHED_FILE_BYTES = 64 * 1024 * 1024
MAX_HASHED_DISTRIBUTION_BYTES = 512 * 1024 * 1024
MAX_HASHED_COLLECTION_BYTES = 2 * 1024 * 1024 * 1024
@@ -56,17 +60,17 @@ NEGATIVE_RESULTS = {
}
PROOF_REQUIREMENTS = {
"target_environment": (
"A target-run result bound to this assessment release and installed-evidence digest.",
"A target-run result bound to this assessment release and installed evidence whose release origin is independently anchored.",
"An independently trusted authority key permitted for target_environment proof.",
"Opaque control IDs and content hashes for the target acceptance artifacts.",
),
"external_providers": (
"Provider acceptance results bound to this assessment release and installed-evidence digest.",
"Provider acceptance results bound to this assessment release and installed evidence whose release origin is independently anchored.",
"An independently trusted authority key permitted for external_providers proof.",
"Opaque control IDs and content hashes; credentials and endpoint identifiers stay outside the report.",
),
"production_approval": (
"An explicit approval bound to this assessment release and installed-evidence digest.",
"An explicit approval bound to this assessment release and installed evidence whose release origin is independently anchored.",
"An independently provisioned authority key permitted for production_approval.",
"An unexpired signed proof bundle; an assessment or operator cannot approve itself.",
),
@@ -104,6 +108,14 @@ class CollectionHashBudget:
remaining_bytes: int = MAX_HASHED_COLLECTION_BYTES
@dataclass(frozen=True, slots=True)
class RecordEntry:
path: str
hash_mode: str | None
hash_value: str | None
size: int | None
def validate_payload(
*, payload: dict[str, Any], schema: dict[str, Any]
) -> tuple[str, ...]:
@@ -231,7 +243,7 @@ def collect_installed_composition(
sorted_issues.sort(key=lambda item: (item["package_name"], item["code"]))
return {
"$schema": "./installed-composition-evidence.schema.json",
"schema_version": "0.2.0",
"schema_version": "0.3.0",
"evidence_kind": "govoplan.installed-composition",
"assessment_id": _safe_opaque_id(
assessment.get("assessment_id"), fallback="invalid-assessment"
@@ -264,6 +276,7 @@ def review_installed_composition(
observation_mode: str = "imported_unsigned",
verification_time: datetime | None = None,
verification_mode: str = "current",
catalog_trusted: bool = False,
) -> InstalledEvidenceReview:
if evidence is None:
return InstalledEvidenceReview(
@@ -337,6 +350,15 @@ def review_installed_composition(
("assessment.installed_composition",),
)
)
if catalog_trusted is not True:
findings.append(
EvidenceFinding(
"blocker",
"installed_catalog_trust_unavailable",
"Installed-composition proof depends on a valid signed catalog.",
("assessment.release", "assessment.installed_composition"),
)
)
changes: list[dict[str, Any]] = []
changed_repositories: set[str] = set()
affected_module_ids: set[str] = set()
@@ -391,6 +413,8 @@ def review_installed_composition(
)
if effective_verification_mode == "invalid":
observation_trusted = False
if catalog_trusted is not True:
observation_trusted = False
expected_release = (
assessment.get("release", {}).get("ref")
if isinstance(assessment.get("release"), dict)
@@ -501,7 +525,7 @@ def review_installed_composition(
record_verified = 0
generated_unhashed_file_count = 0
provenance_expected = 0
provenance_anchored = 0
provenance_declared_match = 0
provenance_mutable = 0
provenance_unanchored = 0
artifact_valid = binding_valid and not duplicate_packages
@@ -648,6 +672,23 @@ def review_installed_composition(
provenance_kind = (
str(provenance.get("kind") or "") if isinstance(provenance, dict) else ""
)
provenance_basis = (
str(provenance.get("basis") or "") if isinstance(provenance, dict) else ""
)
if provenance_basis != "local-pep610-metadata":
artifact_valid = False
provenance_unanchored += 1
_record_change(
findings=findings,
changes=changes,
changed_repositories=changed_repositories,
affected_module_ids=affected_module_ids,
component=component,
kind="installed_source_metadata_invalid",
code="installed_source_metadata_basis_invalid",
message=f"Installed distribution {package_name!r} does not identify its source statement as local PEP 610 metadata.",
)
continue
if provenance_kind == "vcs-commit":
commit = str(provenance.get("commit") or "").lower()
selected_version = selected_versions.get(repository)
@@ -660,7 +701,7 @@ def review_installed_composition(
or commit == selected_commit.lower()
)
if commit_matches and selected_matches:
provenance_anchored += 1
provenance_declared_match += 1
else:
artifact_valid = False
_record_change(
@@ -671,7 +712,7 @@ def review_installed_composition(
component=component,
kind="installed_commit_mismatch",
code="installed_source_commit_mismatch",
message=f"Installed immutable VCS provenance for {package_name!r} does not match the assessed or signed selected-unit commit.",
message=f"Installed distribution {package_name!r} declares a local PEP 610 VCS commit that does not match the assessed or signed selected-unit commit.",
)
elif provenance_kind in {"editable-vcs", "editable-local", "local-directory"}:
provenance_mutable += 1
@@ -684,7 +725,7 @@ def review_installed_composition(
component=component,
kind="installed_source_mutable",
code="installed_source_mutable",
message=f"Installed distribution {package_name!r} is editable or directory-backed and is not immutable release evidence.",
message=f"Installed distribution {package_name!r} declares an editable or directory-backed local source.",
)
else:
provenance_unanchored += 1
@@ -697,7 +738,7 @@ def review_installed_composition(
component=component,
kind="installed_source_unanchored",
code="installed_source_unanchored",
message=f"Installed distribution {package_name!r} has no source provenance anchored to the assessed release.",
message=f"Installed distribution {package_name!r} has no local PEP 610 source statement matching the assessed release.",
)
expected_packages = set(expected_by_package)
@@ -785,13 +826,25 @@ def review_installed_composition(
},
"installed_source_provenance": {
"checked": provenance_checked,
"valid": provenance_anchored == provenance_expected
"valid": provenance_declared_match == provenance_expected
if provenance_checked
else None,
"anchored_distribution_count": provenance_anchored,
"basis": "local-pep610-metadata",
"declared_match_distribution_count": provenance_declared_match,
"mutable_distribution_count": provenance_mutable,
"unanchored_distribution_count": provenance_unanchored,
"expected_distribution_count": provenance_expected,
"release_origin_bound": False,
},
"installed_release_origin": {
"checked": False,
"valid": None,
"release_origin_bound": False,
"anchored_artifact_digest_count": 0,
"expected_distribution_count": provenance_expected,
"required_evidence": (
"An independently anchored artifact digest or signed installer receipt that binds each installed payload to the signed release catalog.",
),
},
"runtime_activation": {
"checked": False,
@@ -807,6 +860,7 @@ def review_installed_composition(
"collected_at": _iso_datetime(collected_at),
"evaluated_at": _iso_datetime(now),
"verification_mode": effective_verification_mode,
"catalog_trusted": catalog_trusted is True,
"freshness_window_seconds": int(MAX_LOCAL_OBSERVATION_AGE.total_seconds()),
},
}
@@ -949,6 +1003,9 @@ def review_boundary_evidence(
)
installed_digest = installed_review.evidence_sha256
installed_scope = installed_review.proof_scope.get("installed_artifacts", {})
installed_origin_scope = installed_review.proof_scope.get(
"installed_release_origin", {}
)
if (
installed_digest is None
or evidence.get("installed_evidence_sha256") != installed_digest
@@ -962,6 +1019,15 @@ def review_boundary_evidence(
("assessment.installed_composition", "assessment.external_proof"),
)
)
if installed_origin_scope.get("valid") is not True:
findings.append(
EvidenceFinding(
"blocker",
"boundary_installed_release_origin_untrusted",
"Boundary evidence requires an independently anchored digest or signed installer receipt for every installed release artifact; local PEP 610 and RECORD metadata are insufficient.",
("assessment.installed_composition", "assessment.external_proof"),
)
)
issued_at = _datetime(evidence.get("issued_at"))
expires_at = _datetime(evidence.get("expires_at"))
@@ -1295,19 +1361,19 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
try:
raw = distribution.read_text("direct_url.json")
except Exception:
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
if raw is None:
return {"kind": "index-or-unknown"}
return _local_source_metadata("index-or-unknown")
if not isinstance(raw, str) or len(raw) > MAX_DIRECT_URL_BYTES:
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
if len(raw.encode("utf-8")) > MAX_DIRECT_URL_BYTES:
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
try:
direct_url = json.loads(raw)
except (TypeError, json.JSONDecodeError):
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
if not isinstance(direct_url, dict):
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
raw_url = direct_url.get("url")
if (
not isinstance(raw_url, str)
@@ -1315,13 +1381,13 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
or len(raw_url) > 2048
or any(character.isspace() or ord(character) < 32 for character in raw_url)
):
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
try:
parsed_url = urlsplit(raw_url)
except ValueError:
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
if parsed_url.password is not None or parsed_url.query or parsed_url.fragment:
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
vcs_info = direct_url.get("vcs_info")
directory_info = direct_url.get("dir_info")
archive_info = direct_url.get("archive_info")
@@ -1335,10 +1401,10 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
if value is not None
)
if len(provenance_forms) != 1:
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
if isinstance(vcs_info, dict):
if vcs_info.get("vcs") != "git":
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
commit = str(vcs_info.get("commit_id") or "").lower()
requested_revision = vcs_info.get("requested_revision")
if (
@@ -1359,8 +1425,8 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
)
)
):
return {"kind": "malformed-direct-url"}
return {"kind": "vcs-commit", "commit": commit}
return _local_source_metadata("malformed-direct-url")
return _local_source_metadata("vcs-commit", commit=commit)
if isinstance(archive_info, dict):
if (
parsed_url.scheme not in {"file", "https"}
@@ -1370,7 +1436,7 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
and (not parsed_url.hostname or parsed_url.username)
)
):
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
hashes = archive_info.get("hashes")
digest = hashes.get("sha256") if isinstance(hashes, dict) else None
if digest is None:
@@ -1379,8 +1445,8 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
digest = legacy.removeprefix("sha256=")
digest_text = str(digest or "").lower()
if SHA256_PATTERN.fullmatch(digest_text):
return {"kind": "archive", "sha256": digest_text}
return {"kind": "malformed-direct-url"}
return _local_source_metadata("archive", sha256=digest_text)
return _local_source_metadata("malformed-direct-url")
if isinstance(directory_info, dict):
editable = directory_info.get("editable", False)
if (
@@ -1388,9 +1454,142 @@ def _source_provenance(distribution: metadata.Distribution) -> dict[str, str]:
or not parsed_url.path
or not isinstance(editable, bool)
):
return {"kind": "malformed-direct-url"}
return {"kind": "editable-local" if editable else "local-directory"}
return {"kind": "malformed-direct-url"}
return _local_source_metadata("malformed-direct-url")
return _local_source_metadata(
"editable-local" if editable else "local-directory"
)
return _local_source_metadata("malformed-direct-url")
def _local_source_metadata(kind: str, **values: str) -> dict[str, str]:
return {"basis": "local-pep610-metadata", "kind": kind, **values}
def _read_record_entries(
*,
distribution: metadata.Distribution,
distribution_root: Path,
max_entries: int,
) -> tuple[tuple[RecordEntry, ...], int, str]:
"""Read RECORD itself without importlib's missing-path filtering.
``Distribution.files`` is an interpreted convenience API rather than the
raw declaration being attested. Reading the metadata file directly lets
this collector retain missing and malformed declarations and enforce byte
and row limits before resolving any untrusted payload path.
"""
metadata_root_value = getattr(distribution, "_path", None)
if metadata_root_value is None:
return (), 0, "unavailable"
try:
metadata_root = Path(os.fspath(metadata_root_value))
if metadata_root.is_symlink():
return (), 0, "unavailable"
resolved_metadata_root = metadata_root.resolve()
except (OSError, TypeError, ValueError):
return (), 0, "unavailable"
if not _is_relative_to(resolved_metadata_root, distribution_root):
return (), 0, "unavailable"
record_path = resolved_metadata_root / "RECORD"
try:
if record_path.is_symlink():
return (), 0, "unavailable"
encoded, exceeded, stable = _bounded_regular_file_bytes(
record_path,
max_bytes=MAX_RECORD_BYTES,
)
except OSError:
return (), 0, "unavailable"
if exceeded:
return (), 0, "limit-exceeded"
if not stable:
return (), 1, "unavailable"
try:
text = encoded.decode("utf-8")
except UnicodeDecodeError:
return (), 1, "unavailable"
entries: list[RecordEntry] = []
malformed_rows = 0
declared_paths: set[str] = set()
try:
rows = csv.reader(io.StringIO(text, newline=""))
for row in rows:
if len(entries) + malformed_rows >= max_entries:
return (), 0, "limit-exceeded"
if len(row) != 3:
malformed_rows += 1
continue
raw_path, raw_hash, raw_size = row
if (
not raw_path
or len(raw_path) > MAX_RECORD_PATH_CHARACTERS
or any(ord(character) < 32 for character in raw_path)
or (raw_size and (len(raw_size) > 20 or not raw_size.isdecimal()))
):
malformed_rows += 1
continue
declared_path = str(PurePosixPath(raw_path.replace("\\", "/")))
if declared_path in declared_paths:
malformed_rows += 1
continue
declared_paths.add(declared_path)
if raw_hash:
hash_mode, separator, hash_value = raw_hash.partition("=")
if not separator or not hash_mode or not hash_value:
hash_mode = raw_hash
hash_value = ""
else:
hash_mode = None
hash_value = None
entries.append(
RecordEntry(
path=raw_path,
hash_mode=hash_mode,
hash_value=hash_value,
size=int(raw_size) if raw_size else None,
)
)
except (csv.Error, ValueError):
return (), 1, "unavailable"
return tuple(entries), malformed_rows, "ok"
def _bounded_regular_file_bytes(
path: Path,
*,
max_bytes: int,
) -> tuple[bytes, bool, bool]:
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_NONBLOCK", 0)
descriptor = os.open(path, flags)
chunks: list[bytes] = []
total = 0
try:
initial = os.fstat(descriptor)
if not stat.S_ISREG(initial.st_mode):
raise OSError("RECORD metadata is not a regular file")
if initial.st_size > max_bytes:
return b"", True, True
while total <= max_bytes:
chunk = os.read(descriptor, min(1024 * 1024, max_bytes + 1 - total))
if not chunk:
break
chunks.append(chunk)
total += len(chunk)
final = os.fstat(descriptor)
finally:
os.close(descriptor)
exceeded = total > max_bytes or final.st_size > max_bytes
stable = (
not exceeded
and total == initial.st_size
and final.st_size == initial.st_size
and (final.st_dev, final.st_ino) == (initial.st_dev, initial.st_ino)
and final.st_mtime_ns == initial.st_mtime_ns
and final.st_ctime_ns == initial.st_ctime_ns
)
return b"".join(chunks), exceeded, stable
def _record_integrity(
@@ -1407,53 +1606,84 @@ def _record_integrity(
"missing_file_count": 0,
"mismatched_file_count": 0,
}
try:
files = tuple(distribution.files or ())
except Exception:
files = ()
if not files:
return {"status": "unavailable", **counts}
if len(files) > MAX_DISTRIBUTION_FILES or len(files) > budget.remaining_files:
budget.remaining_files = 0
return {"status": "limit-exceeded", **counts}
budget.remaining_files -= len(files)
try:
distribution_root = Path(distribution.locate_file("")).resolve()
installation_root = Path(sys.prefix).resolve()
except OSError:
except Exception:
return {"status": "unavailable", **counts}
if not _trusted_distribution_root(distribution_root):
return {"status": "unavailable", **counts}
entries, malformed_rows, record_status = _read_record_entries(
distribution=distribution,
distribution_root=distribution_root,
max_entries=min(MAX_DISTRIBUTION_FILES, budget.remaining_files),
)
if record_status == "limit-exceeded":
budget.remaining_files = 0
return {"status": "limit-exceeded", **counts}
if record_status != "ok":
counts["unverifiable_file_count"] = malformed_rows
return {"status": "unavailable", **counts}
record_file_count = len(entries) + malformed_rows
if record_file_count == 0:
return {"status": "unavailable", **counts}
budget.remaining_files -= record_file_count
counts["unverifiable_file_count"] = malformed_rows
declared_scripts = _declared_distribution_scripts(distribution)
owner_prefix = package_name.replace("-", "_")
resolved_entries: list[tuple[object, Path | None]] = [
resolved_entries: list[tuple[RecordEntry, Path | None]] = [
(
package_path,
entry,
_resolve_record_path(
distribution=distribution,
package_path=package_path,
package_path=entry.path,
distribution_root=distribution_root,
installation_root=installation_root,
owner_prefix=owner_prefix,
declared_scripts=declared_scripts,
),
)
for package_path in files
for entry in entries
]
resolved_path_counts: dict[Path, int] = {}
for _, resolved_path in resolved_entries:
if resolved_path is not None:
resolved_path_counts[resolved_path] = (
resolved_path_counts.get(resolved_path, 0) + 1
)
duplicate_resolved_paths = {
path for path, count in resolved_path_counts.items() if count > 1
}
counts["unverifiable_file_count"] += sum(
resolved_path_counts[path] for path in duplicate_resolved_paths
)
hashed_payload_paths = {
resolved_path
for package_path, resolved_path in resolved_entries
for entry, resolved_path in resolved_entries
if resolved_path is not None
and getattr(getattr(package_path, "hash", None), "mode", None) == "sha256"
and resolved_path not in duplicate_resolved_paths
and entry.hash_mode == "sha256"
}
total_hashed_bytes = 0
limit_exceeded = False
for package_path, resolved_path in resolved_entries:
hash_info = getattr(package_path, "hash", None)
for entry, resolved_path in resolved_entries:
if resolved_path is None:
counts["unverifiable_file_count"] += 1
continue
if hash_info is None:
if resolved_path in duplicate_resolved_paths:
continue
try:
file_stat = resolved_path.lstat()
except OSError:
counts["missing_file_count"] += 1
continue
if not stat.S_ISREG(file_stat.st_mode):
counts["missing_file_count"] += 1
continue
if entry.size is not None and file_stat.st_size != entry.size:
counts["mismatched_file_count"] += 1
continue
if entry.hash_mode is None:
if _permitted_unhashed_record_path(
resolved_path,
distribution_root=distribution_root,
@@ -1468,17 +1698,9 @@ def _record_integrity(
else:
counts["unverifiable_file_count"] += 1
continue
if getattr(hash_info, "mode", None) != "sha256":
if entry.hash_mode != "sha256":
counts["unverifiable_file_count"] += 1
continue
try:
file_stat = resolved_path.stat()
except OSError:
counts["missing_file_count"] += 1
continue
if not stat.S_ISREG(file_stat.st_mode):
counts["missing_file_count"] += 1
continue
remaining_distribution_bytes = (
MAX_HASHED_DISTRIBUTION_BYTES - total_hashed_bytes
)
@@ -1490,7 +1712,7 @@ def _record_integrity(
if allowed_bytes <= 0 or file_stat.st_size > allowed_bytes:
limit_exceeded = True
continue
expected = _record_hash_bytes(str(getattr(hash_info, "value", "")))
expected = _record_hash_bytes(entry.hash_value or "")
if expected is None:
counts["unverifiable_file_count"] += 1
continue
@@ -1541,7 +1763,7 @@ def _resolve_record_path(
if unresolved_path.is_symlink():
return None
resolved_path = unresolved_path.resolve()
except OSError:
except (OSError, TypeError, ValueError):
return None
has_parent_traversal = ".." in record_path.parts
if not has_parent_traversal:
@@ -1704,10 +1926,49 @@ def _active_authority_keys(
seen: set[str] = set()
public_key_owners: dict[bytes, str] = {}
duplicate_public_keys: set[bytes] = set()
for item in authority_keyring.get("keys", []):
raw_keys = authority_keyring.get("keys")
if not isinstance(raw_keys, list):
return {}, (
EvidenceFinding(
"blocker",
"boundary_authority_key_invalid",
"Proof-authority keyring does not contain a valid key list.",
("assessment.external_proof",),
),
)
for item in raw_keys:
if not isinstance(item, dict):
findings.append(
EvidenceFinding(
"blocker",
"boundary_authority_key_invalid",
"Proof-authority keyring contains a malformed key entry.",
("assessment.external_proof",),
)
)
continue
key_id = str(item.get("key_id") or "")
status = item.get("status")
raw_allowed_scopes = item.get("allowed_scopes")
if (
len(key_id) > 160
or OPAQUE_ID_PATTERN.fullmatch(key_id) is None
or status not in {"active", "next", "revoked", "disabled", "retired"}
or not isinstance(raw_allowed_scopes, list)
or not raw_allowed_scopes
or any(not isinstance(scope, str) for scope in raw_allowed_scopes)
or len(raw_allowed_scopes) != len(set(raw_allowed_scopes))
or any(scope not in PROOF_REQUIREMENTS for scope in raw_allowed_scopes)
):
findings.append(
EvidenceFinding(
"blocker",
"boundary_authority_key_invalid",
"Proof-authority keyring contains a malformed key entry.",
("assessment.external_proof",),
)
)
continue
if key_id in seen:
findings.append(
EvidenceFinding(
@@ -1725,6 +1986,36 @@ def _active_authority_keys(
)
Ed25519PublicKey.from_public_bytes(public_key)
except ValueError:
findings.append(
EvidenceFinding(
"blocker",
"boundary_authority_key_invalid",
"Proof-authority keyring contains invalid Ed25519 public-key material.",
("assessment.external_proof",),
)
)
continue
raw_not_before = item.get("not_before")
raw_not_after = item.get("not_after")
not_before = _datetime(raw_not_before)
not_after = _datetime(raw_not_after)
if (
(raw_not_before is not None and not_before is None)
or (raw_not_after is not None and not_after is None)
or (
not_before is not None
and not_after is not None
and not_before >= not_after
)
):
findings.append(
EvidenceFinding(
"blocker",
"boundary_authority_key_interval_invalid",
"Proof-authority keyring contains an invalid or empty key-validity interval.",
("assessment.external_proof",),
)
)
continue
previous_owner = public_key_owners.get(public_key)
if previous_owner is not None and previous_owner != key_id:
@@ -1741,10 +2032,8 @@ def _active_authority_keys(
result.pop(previous_owner, None)
continue
public_key_owners[public_key] = key_id
if item.get("status") not in {"active", "next"}:
if status not in {"active", "next"}:
continue
not_before = _datetime(item.get("not_before"))
not_after = _datetime(item.get("not_after"))
if (not_before is not None and verification_time < not_before) or (
not_after is not None and verification_time >= not_after
):
@@ -1761,9 +2050,12 @@ def _active_authority_keys(
continue
result[key_id] = (
public_key,
frozenset(str(value) for value in item.get("allowed_scopes", [])),
frozenset(raw_allowed_scopes),
)
return result, tuple(findings)
# A supplied authority keyring is one trust root. Selecting usable members
# out of a malformed set would let a valid-looking sibling conceal an
# invalid interval, duplicate identity, or ambiguous key assignment.
return ({} if findings else result), tuple(findings)
def _record_change(
@@ -1810,7 +2102,20 @@ def _unchecked_installed_scope() -> dict[str, Any]:
),
},
"installed_record_integrity": {"checked": False, "valid": None},
"installed_source_provenance": {"checked": False, "valid": None},
"installed_source_provenance": {
"checked": False,
"valid": None,
"basis": "local-pep610-metadata",
"release_origin_bound": False,
},
"installed_release_origin": {
"checked": False,
"valid": None,
"release_origin_bound": False,
"required_evidence": (
"An independently anchored artifact digest or signed installer receipt bound to the signed release catalog.",
),
},
"runtime_activation": {
"checked": False,
"valid": None,