Skip to content

reject empty subjectAltName and issuerAltName sequences - #15472

Merged
alex merged 3 commits into
pyca:mainfrom
dxbjavid:empty-san-ian-sequence
Oct 11, 2026
Merged

alex merged 3 commits into
pyca:mainfrom
dxbjavid:empty-san-ian-sequence

Conversation

@dxbjavid

Copy link
Copy Markdown
Contributor

RFC 5280 defines subjectAltName and issuerAltName as a GeneralNames value, which is a SEQUENCE of one or more GeneralName, but the parser accepted an empty sequence, so a malformed certificate or CRL carrying a zero-entry SAN or IAN parsed to an empty extension rather than being rejected. The check sits in parse_general_names rather than on the GeneralNames type alias because the path validation engine reuses that alias and relies on an empty sequence to stand in for a certificate with no SAN. This rejects an empty sequence when the extension is parsed, matching the constraint and the behaviour already in place for an empty extendedKeyUsage.

Comment thread src/rust/src/x509/common.rs Outdated
// RFC 5280, so an empty sequence is malformed. The path validation engine
// represents a certificate with no subjectAltName using its own empty
// sequence and does not call this.
if gn_seq.clone().next().is_none() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SequenceOf takes a MINIMUM_LEN, is there a reason not to just set that to 1?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i looked at that first, but the SubjectAlternativeName and IssuerAlternativeName aliases are shared with the path validation engine, which stands in for a certificate with no SAN by parsing an empty sequence into SubjectAlternativeName (the \x30\x00 parse in cryptography-x509-verification/src/lib.rs). setting MINIMUM_LEN to 1 on the alias would make that parse fail. keeping the check in parse_general_names also means the other GeneralNames users that go through it, authorityCertIssuer and the CRL distribution point names, pick up the same 1..MAX constraint, since 5280 defines them all the same way. happy to move it to a type-level constraint if you'd rather give verification its own zero-minimum type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I think we should probably fix the \x30\x00 callsites to just store an Option<SequenceOf<>>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. set MINIMUM_LEN to 1 on both aliases and made the verification NameChain store an Option instead of parsing the empty \x30\x00 sequence, so the empty rejection now comes from the type. parse_general_names is generic over the minimum length now so the len-0 GeneralNames callers still go through unchanged. rust builds clean.

@alex

alex commented Aug 22, 2026

Copy link
Copy Markdown
Member

@mhils it looks like mitmproxy's tests rely on SANs that are 0 length, even though they're not permitted by the RFC. Is that intentional, or inadveratnat?

@dxbjavid

dxbjavid commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

makes sense to settle that before this lands. if the mitmproxy breakage means a hard reject at parse time is too disruptive, i'm happy to adjust the approach once you and mhils have a view on it.

@mhils

mhils commented Oct 5, 2026

Copy link
Copy Markdown
Member

Apologies for missing this initially. This looks inadveratnat, I'll fix it.

@mhils

mhils commented Oct 5, 2026

Copy link
Copy Markdown
Member

CI should be fixed!

@alex

alex commented Oct 7, 2026

Copy link
Copy Markdown
Member

Awesome, thanks @mhils !

@dxbjavid
dxbjavid force-pushed the empty-san-ian-sequence branch from a0ecb80 to bbf0748 Compare October 7, 2026 06:21
@dxbjavid

dxbjavid commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

thanks for sorting the mitmproxy side. i've rebased this on main to clear the changelog conflict, so it should now run clean against the fixed downstream tests. no code changes from the earlier review, just the rebase.

@alex

alex commented Oct 10, 2026

Copy link
Copy Markdown
Member

Looks like there's some spelling issues in the docs :-)

@dxbjavid

Copy link
Copy Markdown
Contributor Author

good catch, that was the spelling job tripping on the bare camelCase names. wrapped both in literals so the checker skips them, same as the changelog entry already does.

@alex
alex merged commit 2b8e52f into pyca:main Oct 11, 2026
69 checks passed
@dxbjavid

Copy link
Copy Markdown
Contributor Author

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants