Repository navigation
fix(pe): reject malformed and repeated certificate extensions - #8928
Plastic-time wants to merge 1 commit into
Conversation
RFC 5280 4.1 defines an Extension as extnID, an optional critical BOOLEAN and an extnValue OCTET STRING. Section 4.2 says a certificate MUST NOT include more than one instance of an extension. The decoder only checked that extensions were a SEQUENCE. Any entry, and any repeat, was accepted.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
[Medium impact] The PR appears safe to merge; no actionable issues were found. SummaryAdds extension checks at the shared X.509 decoder boundary.
Supersession could not be checked on GitHub because authentication was unavailable. Local history showed no replacement change. Tests were not run during this review. Reviews (1) · Last reviewed commit: "fix(pe): reject malformed and repeated c..." · Reviewed by Greptile |
Summary
The PE certificate decoder checks that a certificate's extensions are a SEQUENCE, but never looks inside it. Any entry is accepted, and so is the same extension listed twice.
No linked issue. Found while reading the decoder next to the other certificate-field fixes.
Problem and expected behavior
RFC 5280 §4.1 defines each entry:
RFC 5280 §4.2 adds: "A certificate MUST NOT include more than one instance of a particular extension."
On
main, a certificate breaking either rule is decoded and reported as usual. pyca/cryptography refuses the same certificates. It reportsDuplicateExtensionfor a repeat and a parse error for a malformed entry.Change and scope
requireExtensionsruns on the extensions SEQUENCE infinishTbsCertificate.critical FALSEand a TRUE other than0xFFare still accepted.Follow the contribution scope. Ordinary fix within existing boundaries; maintainer scope decision not applicable.
Contract and boundary impact
finishTbsCertificateinsrc/native/pe/PeCertificateAsn1.ts.invalid_request, like other malformed certificate fields.docs/public/product-catalog.json), package, or installation impact: none.Expected effects (check known effects; use documentation-only on its own).
Unchecked items do not establish absence; leave uncertainties visible.
Evidence and regression coverage
src/native/pe/PeCertificateParser.test.ts› "rejects malformed and repeated certificate extensions". It refuses eight malformed entries and a repeat that is not adjacent. It accepts two distinct extensions, one marked critical.src/native/pe/PeCertificateAsn1.tsreset tomain(d896ab7). On this branch they give 1 failed / 85 passed. The remaining failure istests/boundary/filesystem/peCertificates.test.ts› "reports non-file and malformed PE selections as caller input errors". It isEPERMcreating a symlink on this Windows host, and it fails the same way onmain.pkcs7SignedDataFixture()and list its subjectKeyIdentifier extension twice. Onmain,inspect-pe-certificates --jsonexits 0 and reports the certificate with serial11223344. On this branch it exits 1 withinvalid_requestandPKCS#7 signedData is malformed: TBSCertificate repeats extension 2.5.29.14.load_der_x509_certificate, then.extensions).mainaccepts all 16. cryptography refuses 12.critical FALSE. cryptography refuses it as an encoded DER default. This branch keeps accepting it on purpose (see scope).mainexactly. 49 decode, with 117 certificates, and every one passes the new check. The same 11 fail as onmain: 8 hit the ASN.1 nesting limit that fix(pe): admit Authenticode nesting depth of signed Windows binaries #7160 addresses, and 3 carry vendor bytes after the PKCS#7. 2 are catalog-signed, so Windows reports a different signer.For evidence-bearing changes:
Validation performed
Windows 11 x64 (10.0.26200), Node 24.22.1, base
maind896ab7.npm run test:focused --oversrc/native/pe/PeCertificateParser.test.ts,src/application/binaryDiagnostics/PeCertificatesService.test.ts,src/domain/native/peCertificates.test.ts,tests/acceptance/peCertificatesCli.test.ts,tests/boundary/filesystem/peCertificates.test.tsandtests/boundary/mcp/peCertificatesMcp.test.ts— 85 passed, 1 failed (EPERMsymlink, same onmain). With the source reset tomain: 2 failed / 84 passed.npm run check:fast(typecheck and lint) — passed.oxfmt --checkon both files — passed.mainand on this branch — results as shown.git merge-treewith fix(pe): reject certificate versions and fields RFC 5280 does not allow #8921, fix(pe): reject a SignerInfo version that does not match its sid #8924, fix(pe): preserve certificate serial number sign #8916 and fix(pe): admit Authenticode nesting depth of signed Windows binaries #7160, which edit the same files: all merge cleanly.Compatibility, safety, and release
Prepared with AI assistance.
Author readiness
Human owner: @Plastic-time
Before merge
type(scope): outcome.