Skip to content

Add X509AuthorityKeyIdentifier to generated leaf certificates - #1899

Merged
waldekmastykarz merged 4 commits into
dotnet:mainfrom
AronUJVARY:bugfix/add_authority_key_identifier_to_leaf_certificates
Oct 1, 2026
Merged

waldekmastykarz merged 4 commits into
dotnet:mainfrom
AronUJVARY:bugfix/add_authority_key_identifier_to_leaf_certificates

Conversation

@AronUJVARY

Copy link
Copy Markdown
Contributor

Python starting at 3.13 defaults to using VERIFY_X509_STRICT in its ssl context (https://docs.python.org/3/library/ssl.html, https://gist.github.com/mdehling/350fc63d286a31b2653aef1362c6b0f5/). This leads to python rejecting the leaf certificates of dev-proxy, complaining about missing authority key identifier. Adding the X509AuthorityKeyIdentifierExtension fixes the issue.

@AronUJVARY
AronUJVARY requested a review from a team as a code owner September 29, 2026 09:02
@AronUJVARY

Copy link
Copy Markdown
Contributor Author

@dotnet-policy-service agree company="Cinemo"

@AronUJVARY
AronUJVARY force-pushed the bugfix/add_authority_key_identifier_to_leaf_certificates branch from b603f73 to 1932ff5 Compare September 29, 2026 09:04
@waldekmastykarz waldekmastykarz added the pr-bugfix Fixes a bug label Sep 29, 2026
@waldekmastykarz

Copy link
Copy Markdown
Collaborator

Thanks a lot for this @AronUJVARY! 🙏 Great catch. Python 3.13 turning on VERIFY_X509_STRICT by default is exactly the kind of thing that silently breaks people, and you're right that our leaf certs should've had an AKI all along. Really appreciate you tracking it down and sending a fix.

Adding X509AuthorityKeyIdentifierExtension to the leaf is the right fix. There's one catch though: CreateFromCertificate(_ca, includeKeyIdentifier: true, ...) throws when the root doesn't have a Subject Key Identifier. We still load roots created by the previous (Titanium-based) engine, and those don't have an SKI, so for folks upgrading this would fail on every HTTPS request. That's also why the test helper needed the SKI added. The test passes now, but it hides the scenario rather than covering it.

Since this is going into v4, which is a major release, we can do this properly instead of working around old certs. Here's what I'd suggest:

  • Treat roots without an SKI as invalid in TryLoadRoot, same as we do for expired/non-CA roots. We then regenerate the root and purge the leaf cache, which the code already handles. Even with an AKI on the leaf, strict mode also requires the CA to have an SKI, so this is needed for Python to work anyway. Optionally, also check that KeyUsage includes keyCertSign.
  • Invalidate cached leaves without a matching AKI in TryLoadLeaf. Leaves are cached for up to a year, so without this, folks on v4 previews would keep getting old leaves that lack the AKI. Checking that the AKI matches the root's SKI also protects us against leaves signed by a different root.
  • Tests: keep the SKI in the helper, and add tests that (1) a root without an SKI gets regenerated, (2) a cached leaf without an AKI gets re-created, and (3) the leaf's AKI key id matches the root's SKI.

With these changes the root is regenerated on upgrade, so people will need to trust it again. That's fine for v4, and I'll call it out in the release notes.

Would you be up for making these changes? If not, no worries at all, just let me know and we'll take it from here. Thanks again!

@AronUJVARY

Copy link
Copy Markdown
Contributor Author

@waldekmastykarz thanks for the feedback, good points! On it!

@AronUJVARY
AronUJVARY marked this pull request as draft September 30, 2026 07:20
@AronUJVARY
AronUJVARY force-pushed the bugfix/add_authority_key_identifier_to_leaf_certificates branch from 3b2856a to be9e655 Compare September 30, 2026 16:42
@AronUJVARY
AronUJVARY marked this pull request as ready for review September 30, 2026 16:43
@AronUJVARY
AronUJVARY force-pushed the bugfix/add_authority_key_identifier_to_leaf_certificates branch from be9e655 to 4fcb5ab Compare September 30, 2026 16:43
@AronUJVARY

Copy link
Copy Markdown
Contributor Author

Hopefully that ticks all the boxes.

With these changes the root is regenerated on upgrade, so people will need to trust it again. That's fine for v4, and I'll call it out in the release notes.

If the root cert already has the SubjectKeyIdentifier and KeyCertSign usage (which root certs generated on v3.3.1 do), re-trusting won't be needed, but I can imagine root certs generated on older revisions might lack some of these.

waldekmastykarz and others added 2 commits October 1, 2026 09:26
- Use camelCase for local variables and parameters
- Dispose the extra root certificate in the mismatched-AKI test
- Use Allman braces and drop trailing blank line

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@waldekmastykarz
waldekmastykarz merged commit 7e9e440 into dotnet:main Oct 1, 2026
4 checks passed
@waldekmastykarz

Copy link
Copy Markdown
Collaborator

Thank you! I pushed an extra commit with a few cosmetic changes, but all good beyond that. Merged!

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

Labels

pr-bugfix Fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants