feat(mcp): add immutable external artifact mirror lane

This commit is contained in:
ogt
2026-07-15 09:42:46 +08:00
parent 618e499471
commit 4dbd5875af
8 changed files with 3292 additions and 8 deletions

View File

@@ -0,0 +1,393 @@
from __future__ import annotations
import base64
import importlib.util
import io
import json
import sys
import tarfile
import tempfile
import unittest
from contextlib import redirect_stdout
from pathlib import Path
from unittest.mock import patch
ROOT = Path(__file__).resolve().parents[3]
CONTROLLER_PATH = ROOT / "scripts/security/external_mcp_artifact_controller.py"
POLICY_PATH = ROOT / "config/mcp/playwright-mcp-artifact-policy.json"
WORKFLOW_PATH = ROOT / ".gitea/workflows/mcp-external-artifact-mirror.yaml"
RUN_ID = "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
TRACE_ID = f"mcp-artifact-{RUN_ID}"
def _load_controller():
spec = importlib.util.spec_from_file_location(
"external_mcp_artifact_controller", CONTROLLER_PATH
)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
controller = _load_controller()
def _verified_packages(policy):
return tuple(
controller.VerifiedPackage(
policy=package,
tarball=b"tarball",
attestation=b"{}",
metadata_sha256="a" * 64,
tarball_sha512_hex=package.sha512_hex,
tarball_sha1=package.shasum_sha1,
attestation_sha256="b" * 64,
unpacked_bytes=1024,
archive_file_count=3,
license_file_count=1,
osv_response_sha256="c" * 64,
vulnerability_ids=(),
)
for package in policy.packages
)
def _tarball(
package,
*,
unsafe_symlink: bool = False,
duplicate_manifest: bool = False,
) -> bytes:
package_json = json.dumps(
{
"name": package.name,
"version": package.version,
"license": package.license,
"dependencies": package.dependencies,
"optionalDependencies": package.optional_dependencies,
}
).encode()
output = io.BytesIO()
with tarfile.open(fileobj=output, mode="w:gz") as archive:
for name, data in (
("package/package.json", package_json),
("package/LICENSE", b"Apache License 2.0"),
):
member = tarfile.TarInfo(name)
member.size = len(data)
archive.addfile(member, io.BytesIO(data))
if duplicate_manifest:
member = tarfile.TarInfo("package/package.json")
member.size = len(package_json)
archive.addfile(member, io.BytesIO(package_json))
if unsafe_symlink:
member = tarfile.TarInfo("package/escape")
member.type = tarfile.SYMTYPE
member.linkname = "../../outside"
archive.addfile(member)
return output.getvalue()
class ExternalMcpArtifactControllerTest(unittest.TestCase):
def test_policy_is_exact_discovery_only_and_fail_closed(self) -> None:
policy = controller.load_policy(POLICY_PATH)
raw = POLICY_PATH.read_text(encoding="utf-8").lower()
self.assertEqual(policy.candidate_id, "external.playwright-verifier")
self.assertEqual(policy.risk_level, "high")
self.assertEqual(len(policy.packages), 3)
self.assertEqual(policy.mirror_tag, "0.0.78-bundle-v1")
self.assertNotIn("@latest", raw)
self.assertNotIn(":latest", raw)
self.assertNotIn("npx -y", raw)
self.assertNotIn("github.com", raw)
self.assertNotIn("ghcr.io", raw)
self.assertTrue(all(package.version for package in policy.packages))
self.assertTrue(all(package.sha512_hex for package in policy.packages))
def test_gitea_workflow_has_no_remote_action_or_floating_supply_chain(self) -> None:
raw = WORKFLOW_PATH.read_text(encoding="utf-8")
lowered = raw.lower()
self.assertNotIn("uses:", lowered)
self.assertNotIn("actions/checkout", lowered)
self.assertNotIn("github.com", lowered)
self.assertNotIn("api.github.com", lowered)
self.assertNotIn("raw.githubusercontent.com", lowered)
self.assertNotIn("codeload.github.com", lowered)
self.assertNotIn("ghcr.io", lowered)
self.assertNotIn("npx -y", lowered)
self.assertNotIn("@latest", lowered)
self.assertNotIn(":latest", lowered)
self.assertNotIn("git push --force", lowered)
self.assertIn("runs-on: awoooi-non110-host", raw)
self.assertIn("docker login", raw)
self.assertIn("--password-stdin", raw)
self.assertIn("docker logout", raw)
self.assertIn("verify_external_mcp_artifact_receipt.py", raw)
self.assertIn("git merge --no-edit gitea/main", raw)
self.assertIn("git push gitea HEAD:main", raw)
self.assertIn('cron: "13 2 * * 3"', raw)
def test_dependency_closure_rejects_drift(self) -> None:
payload = json.loads(POLICY_PATH.read_text(encoding="utf-8"))
payload["packages"][0]["dependencies"]["playwright"] = "1.2.3"
with tempfile.TemporaryDirectory() as temp:
path = Path(temp) / "policy.json"
path.write_text(json.dumps(payload), encoding="utf-8")
with self.assertRaisesRegex(
controller.ControllerError, "dependency_closure_invalid"
):
controller.load_policy(path)
def test_run_and_trace_identity_must_match(self) -> None:
with self.assertRaisesRegex(
controller.ControllerError, "run_trace_identity_mismatch"
):
controller.main(
[
"--policy",
str(POLICY_PATH),
"--run-id",
RUN_ID,
"--trace-id",
"mcp-artifact-00000000-0000-4000-8000-000000000000",
"check",
]
)
def test_noncanonical_run_id_is_rejected(self) -> None:
with self.assertRaisesRegex(controller.ControllerError, "run_id_not_canonical"):
controller.main(
[
"--policy",
str(POLICY_PATH),
"--run-id",
RUN_ID.upper(),
"--trace-id",
TRACE_ID,
"check",
]
)
def test_check_mode_emits_bound_no_write_receipt(self) -> None:
policy = controller.load_policy(POLICY_PATH)
verified = _verified_packages(policy)
with (
patch.object(controller, "verify_upstream_bundle", return_value=verified),
patch.object(controller, "build_cyclonedx_sbom", return_value={}),
patch.object(
controller,
"_write_bundle",
return_value=("d" * 64, "e" * 64),
),
io.StringIO() as output,
redirect_stdout(output),
):
result = controller.main(
[
"--policy",
str(POLICY_PATH),
"--run-id",
RUN_ID,
"--trace-id",
TRACE_ID,
"check",
]
)
receipt = json.loads(output.getvalue())
self.assertEqual(result, 0)
self.assertEqual(receipt["run_id"], RUN_ID)
self.assertEqual(receipt["trace_id"], TRACE_ID)
self.assertEqual(
receipt["status"], "completed_check_mode_pending_independent_verifier"
)
self.assertFalse(receipt["promotion_allowed"])
self.assertFalse(receipt["canary_allowed"])
self.assertFalse(
receipt["stage_receipts"]["sensor_source_receipt"]
["runtime_request_or_response_body_stored"]
)
self.assertTrue(
receipt["stage_receipts"]["sensor_source_receipt"]
["upstream_supply_chain_attestation_bundled"]
)
self.assertEqual(
receipt["stage_receipts"]["rollback_or_no_write_terminal"]["status"],
"no_write_pending_external_verifier",
)
self.assertEqual(
receipt["stage_receipts"]["independent_post_verifier"]["status"],
"pending_external_verifier",
)
def test_mirror_apply_requires_receipt_path(self) -> None:
with self.assertRaisesRegex(
controller.ControllerError, "apply_receipt_path_required"
):
controller.main(
[
"--policy",
str(POLICY_PATH),
"--run-id",
RUN_ID,
"--trace-id",
TRACE_ID,
"mirror",
"--apply",
]
)
def test_tarball_inspection_accepts_exact_manifest(self) -> None:
package = controller.load_policy(POLICY_PATH).packages[0]
unpacked, files, licenses = controller.inspect_tarball(
package,
_tarball(package),
maximum_unpacked_bytes=1024 * 1024,
)
self.assertGreater(unpacked, 0)
self.assertEqual(files, 2)
self.assertEqual(licenses, 1)
def test_tarball_inspection_rejects_symlink(self) -> None:
package = controller.load_policy(POLICY_PATH).packages[0]
with self.assertRaisesRegex(
controller.ControllerError, "package_archive_unsafe_entry"
):
controller.inspect_tarball(
package,
_tarball(package, unsafe_symlink=True),
maximum_unpacked_bytes=1024 * 1024,
)
def test_tarball_inspection_rejects_duplicate_manifest(self) -> None:
package = controller.load_policy(POLICY_PATH).packages[0]
with self.assertRaisesRegex(
controller.ControllerError,
"package_archive_duplicate_or_invalid_file",
):
controller.inspect_tarball(
package,
_tarball(package, duplicate_manifest=True),
maximum_unpacked_bytes=1024 * 1024,
)
def test_slsa_subject_must_match_exact_tarball_digest(self) -> None:
package = controller.load_policy(POLICY_PATH).packages[0]
statement = {
"_type": controller.IN_TOTO_STATEMENT_TYPE,
"predicateType": controller.SLSA_PREDICATE_TYPE,
"subject": [
{
"name": package.slsa_subject_name,
"digest": {"sha512": package.slsa_subject_sha512_hex},
}
],
}
payload = {
"attestations": [
{
"predicateType": controller.SLSA_PREDICATE_TYPE,
"bundle": {
"dsseEnvelope": {
"payload": base64.b64encode(
json.dumps(statement).encode()
).decode()
}
},
}
]
}
controller.validate_slsa_attestation(package, payload)
bad_statement = dict(statement)
bad_statement["subject"] = [
{
"name": package.slsa_subject_name,
"digest": {"sha512": "0" * 128},
}
]
payload["attestations"][0]["bundle"]["dsseEnvelope"]["payload"] = (
base64.b64encode(json.dumps(bad_statement).encode()).decode()
)
with self.assertRaisesRegex(controller.ControllerError, "slsa_subject_mismatch"):
controller.validate_slsa_attestation(package, payload)
def test_sbom_has_exact_npm_purls_and_dependency_edges(self) -> None:
policy = controller.load_policy(POLICY_PATH)
sbom = controller.build_cyclonedx_sbom(
policy,
_verified_packages(policy),
)
refs = {row["bom-ref"] for row in sbom["components"]}
self.assertIn("pkg:npm/%40playwright/mcp@0.0.78", refs)
self.assertNotIn("pkg:npm/%40playwright%2Fmcp@0.0.78", refs)
root = next(
row
for row in sbom["dependencies"]
if row["ref"] == "pkg:npm/%40playwright/mcp@0.0.78"
)
self.assertEqual(len(root["dependsOn"]), 2)
def test_osv_records_fail_closed(self) -> None:
policy = controller.load_policy(POLICY_PATH)
package = policy.packages[0]
class OsvClient:
def post_json(self, *_args, **_kwargs):
return b'{"vulns":[{"id":"OSV-TEST-1"}]}'
response_hash, vulnerabilities = controller._query_osv(
package,
OsvClient(),
policy.maximum_metadata_bytes,
)
self.assertEqual(len(response_hash), 64)
self.assertEqual(vulnerabilities, ("OSV-TEST-1",))
def test_mirror_receipt_never_promotes_runtime(self) -> None:
policy = controller.load_policy(POLICY_PATH)
verified = _verified_packages(policy)
receipt = controller.build_receipt(
policy=policy,
verified=verified,
sbom_sha256="a" * 64,
bundle_manifest_sha256="b" * 64,
run_id=RUN_ID,
trace_id=TRACE_ID,
mode="apply",
internal_mirror_ref=(
"registry.wooo.work/awoooi/mcp-artifacts/playwright-mcp@sha256:"
+ "c" * 64
),
runtime_mirror_ref=(
"192.168.0.110:5000/awoooi/mcp-artifacts/playwright-mcp@sha256:"
+ "c" * 64
),
)
self.assertEqual(
receipt["status"],
"completed_internal_mirror_pending_independent_verifier",
)
self.assertFalse(receipt["promotion_allowed"])
self.assertFalse(receipt["replay_allowed"])
self.assertFalse(receipt["shadow_allowed"])
self.assertFalse(receipt["canary_allowed"])
self.assertFalse(
receipt["stage_receipts"]["bounded_execution"]
["production_route_changed"]
)
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,471 @@
from __future__ import annotations
import base64
import hashlib
import importlib.util
import io
import json
import sys
import tarfile
import tempfile
import unittest
import subprocess
from copy import deepcopy
from pathlib import Path
from urllib.parse import quote
ROOT = Path(__file__).resolve().parents[3]
VERIFIER_PATH = ROOT / "scripts/security/verify_external_mcp_artifact_receipt.py"
RUN_ID = "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
TRACE_ID = f"mcp-artifact-{RUN_ID}"
def _load_verifier():
spec = importlib.util.spec_from_file_location(
"verify_external_mcp_artifact_receipt", VERIFIER_PATH
)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
verifier = _load_verifier()
def _canonical(payload) -> bytes:
return json.dumps(
payload,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
).encode()
def _fixture():
package_data = {
"@playwright/mcp": b"root-package",
"playwright": b"playwright-package",
"playwright-core": b"playwright-core-package",
}
versions = {
"@playwright/mcp": "0.0.78",
"playwright": "1.62.0-alpha-1783623505000",
"playwright-core": "1.62.0-alpha-1783623505000",
}
packages = []
with tempfile.TemporaryDirectory() as temp:
root = Path(temp)
private_key = root / "private.pem"
public_key = root / "public.der"
subprocess.run(
[
"openssl",
"ecparam",
"-name",
"prime256v1",
"-genkey",
"-noout",
"-out",
str(private_key),
],
check=True,
capture_output=True,
)
subprocess.run(
[
"openssl",
"pkey",
"-in",
str(private_key),
"-pubout",
"-outform",
"DER",
"-out",
str(public_key),
],
check=True,
capture_output=True,
)
public_key_base64 = base64.b64encode(public_key.read_bytes()).decode()
for index, (name, data) in enumerate(package_data.items()):
integrity = "sha512-" + base64.b64encode(
hashlib.sha512(data).digest()
).decode()
message = f"{name}@{versions[name]}:{integrity}".encode()
message_path = root / f"message-{index}.bin"
signature_path = root / f"signature-{index}.der"
message_path.write_bytes(message)
subprocess.run(
[
"openssl",
"dgst",
"-sha256",
"-sign",
str(private_key),
"-out",
str(signature_path),
str(message_path),
],
check=True,
capture_output=True,
)
packages.append(
{
"name": name,
"version": versions[name],
"integrity": integrity,
"signature": base64.b64encode(
signature_path.read_bytes()
).decode(),
"slsa_subject_name": (
f"pkg:npm/{quote(name, safe='/')}@{versions[name]}"
),
"slsa_subject_sha512_hex": hashlib.sha512(data).hexdigest(),
"shasum_sha1": hashlib.sha1(
data, usedforsecurity=False
).hexdigest(),
}
)
policy = {
"schema_version": verifier.POLICY_SCHEMA_VERSION,
"work_item_id": "MCP-ARTIFACT-PLAYWRIGHT-TEST",
"candidate_id": "external.playwright-verifier",
"risk_level": "high",
"registry_contract": {
"signature_key": {
"public_key_der_base64": public_key_base64,
}
},
"packages": packages,
"internal_mirror": {
"push_repository": (
"registry.wooo.work/awoooi/mcp-artifacts/playwright-mcp"
),
"runtime_repository": (
"192.168.0.110:5000/awoooi/mcp-artifacts/playwright-mcp"
),
},
}
policy_checksum = "sha256:" + hashlib.sha256(_canonical(policy)).hexdigest()
sbom = {
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"components": [
{
"bom-ref": f"pkg:npm/{quote(row['name'], safe='/')}@{row['version']}"
}
for row in packages
],
}
sbom_bytes = _canonical(sbom) + b"\n"
files = {"artifact/sbom.cdx.json": sbom_bytes}
manifest_rows = []
receipt_rows = []
for row in packages:
safe_name = row["name"].replace("@", "").replace("/", "-")
filename = f"{safe_name}-{row['version']}.tgz"
statement = {
"_type": verifier.IN_TOTO_STATEMENT_TYPE,
"predicateType": verifier.SLSA_PREDICATE_TYPE,
"subject": [
{
"name": row["slsa_subject_name"],
"digest": {"sha512": row["slsa_subject_sha512_hex"]},
}
],
}
attestation = _canonical(
{
"attestations": [
{
"predicateType": verifier.SLSA_PREDICATE_TYPE,
"bundle": {
"dsseEnvelope": {
"payload": base64.b64encode(
_canonical(statement)
).decode()
}
},
}
]
}
)
files[f"artifact/tarballs/{filename}"] = package_data[row["name"]]
files[f"artifact/attestations/{filename}.attestations.json"] = attestation
manifest_rows.append(
{
"name": row["name"],
"version": row["version"],
"tarball_path": f"tarballs/{filename}",
"tarball_sha512_hex": row["slsa_subject_sha512_hex"],
"tarball_sha1": row["shasum_sha1"],
"attestation_path": (
f"attestations/{filename}.attestations.json"
),
"attestation_sha256": hashlib.sha256(attestation).hexdigest(),
"npm_registry_signature_verified": True,
"slsa_subject_verified": True,
"archive_safety_verified": True,
"vulnerability_ids": [],
}
)
receipt_rows.append(
{
"name": row["name"],
"version": row["version"],
"tarball_sha512_hex": row["slsa_subject_sha512_hex"],
"tarball_sha1": row["shasum_sha1"],
"npm_registry_signature_verified": True,
"slsa_subject_verified": True,
"archive_safety_verified": True,
"license_decision": "passed",
"vulnerability_decision": "passed_no_known_osv_records",
"vulnerability_ids": [],
}
)
manifest = {
"candidate_id": policy["candidate_id"],
"work_item_id": policy["work_item_id"],
"policy_checksum": policy_checksum,
"package_count": 3,
"packages": manifest_rows,
"sbom": {"sha256": hashlib.sha256(sbom_bytes).hexdigest()},
"operation_boundaries": {
"mcp_server_started": False,
"browser_started": False,
"runtime_request_or_response_body_stored": False,
},
}
manifest_bytes = _canonical(manifest) + b"\n"
files["artifact/bundle-manifest.json"] = manifest_bytes
digest = "sha256:" + "c" * 64
receipt = {
"schema_version": verifier.CONTROLLER_RECEIPT_SCHEMA_VERSION,
"run_id": RUN_ID,
"trace_id": TRACE_ID,
"work_item_id": policy["work_item_id"],
"candidate_id": policy["candidate_id"],
"risk_level": "high",
"mode": "apply",
"status": "completed_internal_mirror_pending_independent_verifier",
"policy_checksum": policy_checksum,
"packages": receipt_rows,
"internal_mirror_ref": (
policy["internal_mirror"]["push_repository"] + "@" + digest
),
"runtime_mirror_ref": (
policy["internal_mirror"]["runtime_repository"] + "@" + digest
),
"bundle_manifest_sha256": hashlib.sha256(manifest_bytes).hexdigest(),
"cyclonedx_sbom_sha256": hashlib.sha256(sbom_bytes).hexdigest(),
"promotion_allowed": False,
"replay_allowed": False,
"shadow_allowed": False,
"canary_allowed": False,
"stage_receipts": {
"sensor_source_receipt": {
"redirects_followed": 0,
"runtime_request_or_response_body_stored": False,
"upstream_supply_chain_attestation_bundled": True,
},
"check_mode": {
"status": "passed",
"mcp_process_started": False,
"browser_started": False,
"production_write_performed": False,
},
"bounded_execution": {
"status": "internal_oci_bundle_pushed",
"internal_registry_write_performed": True,
"external_runtime_mutation_performed": False,
"production_route_changed": False,
},
"independent_post_verifier": {
"status": "pending_external_verifier",
"internal_digest_ref_verified": False,
},
},
}
return policy, receipt, files
def _write_image_archive(path: Path, files: dict[str, bytes], *, symlink=False):
layer_buffer = io.BytesIO()
with tarfile.open(fileobj=layer_buffer, mode="w") as layer:
for name, data in files.items():
member = tarfile.TarInfo(name)
member.size = len(data)
layer.addfile(member, io.BytesIO(data))
if symlink:
member = tarfile.TarInfo("artifact/unsafe-link")
member.type = tarfile.SYMTYPE
member.linkname = "../../outside"
layer.addfile(member)
layer_bytes = layer_buffer.getvalue()
manifest_bytes = json.dumps([{"Layers": ["layer.tar"]}]).encode()
with tarfile.open(path, mode="w") as outer:
for name, data in (
("manifest.json", manifest_bytes),
("layer.tar", layer_bytes),
):
member = tarfile.TarInfo(name)
member.size = len(data)
outer.addfile(member, io.BytesIO(data))
class ExternalMcpArtifactIndependentVerifierTest(unittest.TestCase):
def test_controller_receipt_identity_and_boundaries_are_validated(self) -> None:
policy, receipt, _ = _fixture()
identity = verifier.validate_controller_receipt(policy, receipt)
self.assertEqual(identity["run_id"], RUN_ID)
self.assertEqual(identity["trace_id"], TRACE_ID)
self.assertEqual(identity["digest"], "sha256:" + "c" * 64)
def test_controller_receipt_rejects_promotion_claim(self) -> None:
policy, receipt, _ = _fixture()
receipt["canary_allowed"] = True
with self.assertRaisesRegex(
verifier.VerifierError,
"controller_receipt_promotion_boundary_invalid",
):
verifier.validate_controller_receipt(policy, receipt)
def test_bundle_files_are_rehashed_independently(self) -> None:
policy, receipt, files = _fixture()
evidence = verifier.verify_bundle_files(
files,
policy=policy,
controller_receipt=receipt,
)
self.assertEqual(evidence["verified_package_count"], 3)
self.assertEqual(evidence["artifact_file_count"], 8)
def test_bundle_tarball_tamper_is_rejected(self) -> None:
policy, receipt, files = _fixture()
tampered = deepcopy(files)
root_tarball = next(
key
for key in tampered
if key.startswith("artifact/tarballs/playwright-mcp-")
)
tampered[root_tarball] += b"tamper"
with self.assertRaisesRegex(
verifier.VerifierError,
"bundle_package_evidence_mismatch",
):
verifier.verify_bundle_files(
tampered,
policy=policy,
controller_receipt=receipt,
)
def test_bundle_extra_file_is_rejected(self) -> None:
policy, receipt, files = _fixture()
files["artifact/unexpected.bin"] = b"unexpected"
with self.assertRaisesRegex(
verifier.VerifierError,
"bundle_file_set_invalid",
):
verifier.verify_bundle_files(
files,
policy=policy,
controller_receipt=receipt,
)
def test_independent_npm_signature_rejects_tamper(self) -> None:
policy, _, files = _fixture()
package = deepcopy(policy["packages"][0])
package["signature"] = base64.b64encode(b"invalid-signature").decode()
tarball_path = next(
key
for key in files
if key.startswith("artifact/tarballs/playwright-mcp-")
)
with self.assertRaisesRegex(
verifier.VerifierError,
"bundled_npm_signature_verification_failed",
):
verifier.verify_bundled_npm_signature(
policy,
package,
files[tarball_path],
)
def test_independent_slsa_subject_rejects_tamper(self) -> None:
policy, _, files = _fixture()
package = deepcopy(policy["packages"][0])
package["slsa_subject_sha512_hex"] = "0" * 128
attestation_path = next(
key
for key in files
if key.startswith("artifact/attestations/playwright-mcp-")
)
with self.assertRaisesRegex(
verifier.VerifierError,
"bundled_slsa_subject_mismatch",
):
verifier.verify_bundled_slsa_subject(
package,
files[attestation_path],
)
def test_image_archive_is_inspected_as_data(self) -> None:
_, _, files = _fixture()
with tempfile.TemporaryDirectory() as temp:
archive = Path(temp) / "image.tar"
_write_image_archive(archive, files)
extracted = verifier.extract_image_files(archive)
self.assertEqual(extracted, files)
def test_image_archive_rejects_symlink(self) -> None:
_, _, files = _fixture()
with tempfile.TemporaryDirectory() as temp:
archive = Path(temp) / "image.tar"
_write_image_archive(archive, files, symlink=True)
with self.assertRaisesRegex(
verifier.VerifierError,
"image_layer_unsafe_entry",
):
verifier.extract_image_files(archive)
def test_verifier_receipt_keeps_runtime_promotion_disabled(self) -> None:
policy, receipt, files = _fixture()
identity = verifier.validate_controller_receipt(policy, receipt)
evidence = verifier.verify_bundle_files(
files,
policy=policy,
controller_receipt=receipt,
)
result = verifier.build_verifier_receipt(
identity=identity,
controller_receipt_bytes=_canonical(receipt) + b"\n",
bundle_evidence=evidence,
)
self.assertEqual(result["status"], "completed_internal_mirror_verified")
self.assertFalse(result["promotion_allowed"])
self.assertFalse(result["replay_allowed"])
self.assertFalse(result["shadow_allowed"])
self.assertFalse(result["canary_allowed"])
self.assertFalse(
result["independent_post_verifier"]["container_or_mcp_started"]
)
if __name__ == "__main__":
unittest.main()