go: crypto/x509: VerifyOptions.Roots does not enforce that certificates are root certificates
What version of Go are you using (go version
)?
$ go version
1.18
What did you do?
https://go.dev/play/p/InpOJXUXnUl
A leaf and intermediate certificate can be provided to the root pool.
What did you expect to see?
I expected that verification would fail due to the lack of root certificates.
What did you see instead?
Successful verification.
It’s unclear to me if this is an intentional feature or a bug.
Should a certificate in a root pool always be a CA certificate (related to RFC5280 4.2.1.9)?
The check that a parent is a CA certificate occurs in CheckSignatureFrom
, called in buildChains
, which is bypassed because the leaf certificate is in the root pool (https://go.dev/src/crypto/x509/verify.go#L781). Allowing a non-CA certificate to be verified successfully against itself seems prone to bugs.
Is a root certificate meant to be defined as a self-signed certificate, or any certificate that forms the trust anchor?
I expected that it must be a self-signed certificate, but an intermediate was permitted. This also seems prone to bugs, for example if a client supports a user-provided certificate chain and the client isn’t enforcing that a chain is formed from a root.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Comments: 17 (9 by maintainers)
I’m not suggesting restricting adding to the pool, I am suggesting rejecting in Verify chains where the signer doesn’t have the isCA bit, even if it’s a root certificate. Direct match of the leaf with the roots pool would still work, because it doesn’t involve a signature check.
In other words, I am suggesting changing this line to also apply the check for root certificates.
https://github.com/golang/go/blob/2580d0e08d5e9f979b943758d3c49877fb2324cb/src/crypto/x509/verify.go#L687-L689
Requiring the isCA bit would would break cert pinning, which is normal (perhaps unfortunately so) for some applications.