Skip to content

Commit 88695b4

Browse files
committed
Handle exceptions when doing PyPI -> Sigstore conversion
1 parent cafa390 commit 88695b4

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/pypi_attestation_models/_impl.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
from typing import TYPE_CHECKING, Annotated, Any, Literal, NewType
1212

1313
import rfc8785
14+
import sigstore.errors
1415
from annotated_types import MinLen # noqa: TCH002
1516
from cryptography import x509
1617
from cryptography.hazmat.primitives import serialization
1718
from pydantic import BaseModel
19+
from pydantic_core import ValidationError
1820
from sigstore.models import Bundle, LogEntry
1921

2022
if TYPE_CHECKING:
@@ -123,9 +125,18 @@ def pypi_to_sigstore(pypi_attestation: Attestation) -> Bundle:
123125
raise InvalidAttestationError(str(err)) from err
124126

125127
tlog_entry = pypi_attestation.verification_material.transparency_entries[0]
128+
try:
129+
certificate = x509.load_der_x509_certificate(certificate_bytes)
130+
except ValueError as err:
131+
raise InvalidAttestationError(str(err)) from err
132+
133+
try:
134+
log_entry = LogEntry._from_dict_rekor(tlog_entry) # noqa: SLF001
135+
except (ValidationError, sigstore.errors.Error) as err:
136+
raise InvalidAttestationError(str(err)) from err
126137

127138
return Bundle.from_parts(
128-
cert=x509.load_der_x509_certificate(certificate_bytes),
139+
cert=certificate,
129140
sig=signature_bytes,
130-
log_entry=LogEntry._from_dict_rekor(tlog_entry), # noqa: SLF001
141+
log_entry=log_entry,
131142
)

test/test_impl.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ def test_pypi_to_sigstore_invalid_certificate_base64() -> None:
5454
impl.pypi_to_sigstore(attestation)
5555

5656

57+
def test_pypi_to_sigstore_invalid_certificate() -> None:
58+
with attestation_path.open("rb") as f:
59+
attestation = impl.Attestation.model_validate_json(f.read())
60+
new_cert = attestation.verification_material.certificate.replace("M", "x")
61+
attestation.verification_material.certificate = new_cert
62+
with pytest.raises(impl.InvalidAttestationError):
63+
impl.pypi_to_sigstore(attestation)
64+
65+
66+
def test_pypi_to_sigstore_invalid_log_entry() -> None:
67+
with attestation_path.open("rb") as f:
68+
attestation = impl.Attestation.model_validate_json(f.read())
69+
new_log_entry = attestation.verification_material.transparency_entries[0]
70+
del new_log_entry["inclusionProof"]
71+
attestation.verification_material.transparency_entries = [new_log_entry]
72+
with pytest.raises(impl.InvalidAttestationError):
73+
impl.pypi_to_sigstore(attestation)
74+
75+
5776
def test_verification_roundtrip() -> None:
5877
# Load an existing Sigstore bundle, check that verification passes,
5978
# convert it to a PyPI attestation and then back again to a Sigstore

0 commit comments

Comments
 (0)