Skip to content

fix(sct): return cert_is_ca result in _cert_is_ca - #1716

Open
xovishnukosuri wants to merge 3 commits into
sigstore:mainfrom
xovishnukosuri:fix/sct-cert-is-ca-return-value
Open

xovishnukosuri wants to merge 3 commits into
sigstore:mainfrom
xovishnukosuri:fix/sct-cert-is-ca-return-value

Conversation

@xovishnukosuri

Copy link
Copy Markdown

What

_cert_is_ca in sigstore/_internal/sct.py calls cert_is_ca(cert) but discards its return value, then unconditionally returns True if no exception was raised:

def _cert_is_ca(cert: Certificate) -> bool:
    try:
        cert_is_ca(cert)          # return value ignored
    except VerificationError as e:
        return False
    return True                   # True even when cert_is_ca() returned False

Why this is a bug

cert_is_ca() (in sigstore/_utils.py) returns False without raising when a certificate has no BasicConstraints extension. In that case _cert_is_ca incorrectly returns True, treating a non-CA certificate as a valid SCT issuer.

This means that during SCT verification for precertificates, a certificate without a BasicConstraints extension would pass the issuer CA check at line 205:

if not _cert_is_ca(issuer_cert):
    raise VerificationError(...)

Fix

Propagate the return value: return cert_is_ca(cert).

All 174 unit tests pass.

Vishnu Kosuri and others added 3 commits March 14, 2026 11:47
…entities

Fulcio ignores the CSR subject field entirely and derives the certificate
identity from the OIDC token directly. Embedding the actual identity claim
in the CSR's EMAIL_ADDRESS attribute causes failures when the claim contains
non-ASCII characters (e.g. emojis in GitHub Actions environment names), since
the field is encoded as IA5String which only allows ASCII.

Replace the identity value with a fixed stub "user@example.com" so that CSR
construction succeeds regardless of the claim content.

Fixes sigstore#1507

Signed-off-by: Vishnu Kosuri <xovishnukosuri@gmail.com>
The try/except block around get_signing_config_path() caught TUFError
only to re-raise it with `raise e`, which resets the traceback to the
re-raise site and hides the actual failure location. Since nothing else
is done in the handler, the block serves no purpose. Remove it and drop
the now-unused TUFError import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_cert_is_ca called cert_is_ca() but discarded its return value,
unconditionally returning True whenever no VerificationError was raised.

cert_is_ca() returns False (without raising) for certificates that
lack a BasicConstraints extension. A non-CA certificate in that state
would pass the issuer CA check in SCT verification.

Fix by propagating the return value with `return cert_is_ca(cert)`.

Signed-off-by: Vishnu <xovishnukosuri@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant