@@ -379,6 +379,28 @@ neither the cert nor its cached parent chain is revoked. The cache is global on-
379379state — once any caller verifies a cert, others reuse it until expiry or revocation,
380380but only under the same parent binding.
381381
382+ ### Certificate parser hardening model
383+
384+ Certificate verification intentionally depends on a narrow X.509/DER subset rather
385+ than on generic BER-like ASN.1 acceptance. The cache key fix makes outside-TBS byte
386+ malleability non-poisoning, but accepting non-canonical certificate structures can
387+ still create parser disagreement with stricter X.509 implementations. Keep the parser
388+ biased toward rejection when a cert uses an alternate encoding for the same apparent
389+ fields.
390+
391+ In particular, hardening changes should preserve these invariants:
392+
393+ - certificate and TBSCertificate containers are the expected X.509 SEQUENCE objects;
394+ - signature INTEGERs use canonical positive DER encodings, not redundant sign bytes;
395+ - the certificate signature BIT STRING contains exactly ` SEQUENCE(INTEGER r, INTEGER s) ` ;
396+ - signed TBS and extension structures do not contain trailing ignored fields;
397+ - known security extensions such as ` basicConstraints ` and ` keyUsage ` are unique.
398+
399+ The value of these checks is defense in depth: an attacker cannot rewrite the signed
400+ TBS of an existing AWS cert without breaking its signature, but the contract should
401+ also avoid trusting certs that are signed yet malformed or interpreted differently by
402+ strict DER/X.509 tooling.
403+
382404### Revocation model
383405AWS's Nitro attestation documentation disables CRL checking in its sample validation
384406flow. This implementation keeps CRL parsing off-chain and exposes an operational
0 commit comments