Skip to content

fix(certificate): UnpackPEM selects leaf by topology, not position#53

Merged
spbsoluble merged 1 commit into
v3from
fix/unpackpem-leaf-selection
Jun 16, 2026
Merged

fix(certificate): UnpackPEM selects leaf by topology, not position#53
spbsoluble merged 1 commit into
v3from
fix/unpackpem-leaf-selection

Conversation

@spbsoluble

Copy link
Copy Markdown
Collaborator

Summary

UnpackPEM selected the leaf certificate positionally — it assumed certificates[0] was the end-entity leaf:

// before
certificate = certificates[0]
caCertificates = certificates[1:]

This returns the root CA as the leaf whenever Keyfactor Command sends a PEM bundle that is not leaf-first. Externally-rooted chains (e.g. DigiCert PKIaaS) are commonly returned root-first, so certificates[0] is the root. Consumers that trust the returned leaf (e.g. the Terraform provider populating common_name / certificate_pem) then persist the root CA's subject, forcing certificate replacement on every run.

Fix

Select the leaf by chain topology using the package's existing findLeafCert (the cert no other cert in the set issued) — the same helper DownloadCertificate already uses for the P7B path. The remaining certs become the CA chain, preserving their original order. Falls back to index 0 when no certs parse, preserving prior behavior for degenerate inputs.

This makes leaf selection order-independent and consistent across the P7B and PEM code paths.

Also included

  • go.sum: added the missing github.com/spbsoluble/go-pkcs12 v0.4.0 module zip checksum (h1:). go.mod pins v0.4.0 but go.sum only carried the /go.mod hash, so clean builds failed with missing go.sum entry for module providing package github.com/spbsoluble/go-pkcs12.

Tests

New v3/api/unpackpem_leaf_test.go:

  • TestUnpackPEM_LeafSelection — root-first / leaf-first / shuffled orderings, 2- and 3-cert chains; asserts the non-CA leaf is selected and the chain length is correct.
  • TestUnpackPEM_WithPrivateKey_RootFirst — root-first bundle with a private key block; asserts both key extraction and correct leaf selection.
  • TestUnpackPEM_SingleCert — single cert returned as leaf, empty chain.

Verified red→green: the root-first / shuffled cases fail against the pre-fix code (return Test Root CA) and pass after the fix. Full ./api/... suite green.

Fixes #52

UnpackPEM assumed certificates[0] was the end-entity leaf, which returns the
root CA when Keyfactor Command sends a non-leaf-first PEM bundle (e.g.
externally-rooted chains returned root-first). Select the leaf via findLeafCert
(already used by DownloadCertificate) so selection is order-independent and
consistent across both code paths; the remaining certs become the CA chain in
their original order.

Also add the missing go-pkcs12 v0.4.0 module zip checksum to go.sum — go.mod
pinned v0.4.0 but go.sum only carried the v0.4.0/go.mod hash, breaking clean
builds (missing go.sum entry).

Adds UnpackPEM leaf-selection regression tests (root-first / leaf-first /
shuffled orderings, 2- and 3-cert chains, and a bundle with a private key).
Verified red->green against the pre-fix code.

Fixes #52
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.

UnpackPEM selects leaf positionally (certificates[0]) — returns root CA on non-leaf-first PEM bundles

1 participant