Skip to content

fix(pem)!: OpenSSL header delimiter + audit citation sweep - #89

Merged
kjanat merged 12 commits into
masterfrom
fix/citation-sweep
Jul 25, 2026
Merged

fix(pem)!: OpenSSL header delimiter + audit citation sweep#89
kjanat merged 12 commits into
masterfrom
fix/citation-sweep

Conversation

@kjanat

@kjanat kjanat commented Jul 24, 2026

Copy link
Copy Markdown
Owner

What

Clears the remaining _audit.md tail — the one Low code finding plus the Low citation errors — so nothing but the doc backlog trails 0.14.0.

RFC 1421 header delimiter (Low code)

parseTraditionalPem keyed on ': ', so a conformant OpenSSL-style encapsulated header written without the space (DEK-Info:AES-256-CBC,…) ended the header scan on its first line and folded the headers into the base64 body, failing with "Traditional PEM encryption headers missing". It now splits on the first : and trims the value. Per the audit, the RFC 1421 citations are scoped to OpenSSL's format (every other reference in the file already says "OpenSSL-style"); RFC 822 folding is not implemented and the citation not kept.

Citation corrections (Low, comment-only)

Each is the audit's prescribed rewording, verified against the vendored spec:

  • pkcs7 module doc scopes the RFC 2315 claim to the OCTET-STRING/X.509 form; curve/digest pairing splits RFC 5753 §8 (curves) from RFC 5754 §2 (digests).
  • PKCS#10 version doc records that the encoded INTEGER is 0 (RFC 2986 §4.1), normalized to the v1 ordinal 1.
  • inhibitAnyPolicy counts additional non-self-issued certificates, exempting an intermediate self-issued CA (RFC 5280 §4.2.1.14).
  • rfc822Name cites RFC 2821 §4.1.2 Mailbox; the DN emailAddress cites PKCS ci: run OpenSSL differential harness in digest-pinned container #9 / RFC 2985 §5.2.1 and its §4.1.2.6 deprecation; the name-shorthand doc drops the incorrect X.501 attribution.
  • OCSP CertID SHA-1 cites RFC 5019 §2.1.1 (RFC 6960 defines no default); the responder attribute map names the X.520 id-at arc plus legacy PKCS ci: run OpenSSL differential harness in digest-pinned container #9.
  • identity cites RFC 9525 with CN fallback scoped to the obsoleted RFC 6125 §6.4.4, and notes §4.1 forbids CN service identification; userConstrainedPolicies documents the RFC 9618 §5.5 (g)(5)-(6) superset relationship.
  • SEC1 ECPrivateKey quotes the constrained RFC 5915 §3 syntax; PBKDF2-params restates the RFC 8018 A.2 salt CHOICE and DEFAULT prf, noting only the specified alternative is accepted.
  • PrintableString cites ITU-T X.680 §41.4 Table 10 (not X.520); OID arc validation splits X.660 (root arcs) from X.690 §8.19.4 (the (X*40)+Y packing that bounds the second arc < 40).

Two audit citation findings — the name-constraints-engine emailAddress-fallback trigger and dNSName leading-period — were already at the audit's target wording on master; no change, deleted from the audit.

Vendored specs

The RFCs these citations reference are vendored (2315, 2821, 2986, 5019, 5753, 5754, 8419, 9525), and an RFC=<n> run rfc fetch helper is added.

Tests

A no-space-after-colon variant of the encrypted-PEM round-trip (Proc-Type:… / DEK-Info:…) imports and matches the original key. Comment-only citation changes have no behavioral test surface.

Gate: typecheck, biome, docs:lint, 1381 tests, 11 OpenSSL differential.

parseTraditionalPem keyed on ': ', so a conformant encapsulated header
written 'DEK-Info:AES-256-CBC,...' ended the header scan early and folded
into the base64 body. Split on the first ':' and trim the value.

Also correct the spec citations the audit flagged, all comment-only:
- pkcs7 module doc scopes the RFC 2315 support claim; curve/digest pairing
  splits RFC 5753 §8 (curves) from RFC 5754 §2 (digests).
- PKCS#10 version doc notes the encoded INTEGER is 0 (RFC 2986 §4.1).
- inhibitAnyPolicy counts non-self-issued certificates (RFC 5280 §4.2.1.14).
- rfc822Name cites RFC 2821 §4.1.2 Mailbox; the DN emailAddress cites
  PKCS #9 / RFC 2985 §5.2.1; name shorthand drops the X.501 attribution.
- OCSP CertID SHA-1 cites RFC 5019 §2.1.1 (RFC 6960 defines no default);
  the responder attribute map names the X.520 id-at arc plus PKCS #9.
- identity cites RFC 9525 with the CN fallback scoped to RFC 6125 §6.4.4;
  userConstrainedPolicies documents the RFC 9618 §5.5 (g)(5)-(6) superset.
- SEC1 ECPrivateKey quotes the constrained RFC 5915 §3 syntax; PBKDF2-params
  restates the RFC 8018 A.2 salt CHOICE and DEFAULT prf.
- PrintableString cites X.680 §41.4 Table 10; OID arcs split X.660 (root)
  from X.690 §8.19.4 (the <40 packing).

Vendor the RFCs these citations reference and add an `rfc` fetch helper.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • cr:review
🚫 Excluded labels (none allowed) (2)
  • wip
  • cr:skip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 98fa391b-de2a-4307-bb8b-ad75f6cb740a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds RFC source files and an RFC-fetching command, preserves PKCS#7 certificate choices, and replaces flattened signer identifiers with discriminated unions. It introduces discriminated models for CRL distribution points, issuing scopes, OCSP statuses, and self-signed key sources. Traditional PEM headers now accept colon-delimited values without spaces while validating names and duplicates. Exhaustiveness guards, public type exports, documentation, compiler settings, and corresponding tests are updated.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

  • KAJ-334 — Directly addresses PEM headers without a space after :.
  • kjanat/micro509#92 — Covers the same parseTraditionalPem header parsing defect.

Possibly related PRs

  • kjanat/micro509#58 — Shares the SubjectAltName rendering paths now receiving exhaustive guards.
  • kjanat/micro509#87 — Overlaps the CRL distribution-point parsing and matching changes.
  • kjanat/micro509#88 — Overlaps X.509 extension and distribution-point validation.

Suggested labels: bug, documentation, rfc-conformance, tests

Poem

PKCS choices sail, while signers align,
PEM headers behave, neat and fine.
CRLs wear tags, OCSP speaks true,
RFCs arrive with a hearty “ahoy!” too.

🚥 Pre-merge checks | ✅ 6 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Semver Version Bump Validation ⚠️ Warning Source files changed, but package.json stayed at 0.13.0 versus origin/master; the PR also contains breaking API changes, so a MAJOR bump was required. Bump a versioned manifest (package.json or VERSION) to a valid SemVer with a MAJOR increment for the breaking API changes, then re-run checks.
Agents.Md Documentation Updated ⚠️ Warning FAIL: PR touches src/test/docs/workflow and adds a CLI helper, but no AGENTS.md files were updated; root/src/docs/test AGENTS exist and stay stale. Update the relevant AGENTS.md files (at least root, src, docs, test, and any applicable subdir) to cover the new API, workflow, and CLI behaviour.
✅ Passed checks (6 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 80.65% which is sufficient. The required threshold is 30.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Changelog Update ✅ Passed Source files changed and CHANGELOG.md was updated under ## [Unreleased]; no version bump is present.
Title check ✅ Passed The title matches the main PEM parsing fix and citation sweep, and it uses a conventional fix prefix.
Description check ✅ Passed The description is directly about the PEM parser fix, vendored RFCs, and citation updates in this changeset.

Comment @coderabbitai help to get the list of available commands.

@kjanat kjanat self-assigned this Jul 24, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jul 24, 2026

Copy link
Copy Markdown
  • micro509-vite-demo

    npm i https://pkg.pr.new/micro509@89
    
    pnpm add https://pkg.pr.new/micro509@89
    
    bun add https://pkg.pr.new/micro509@89
    

commit: b7ec74e

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 24, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
micro509 b7ec74e Commit Preview URL

Branch Preview URL
Jul 25 2026, 10:33 AM

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.22467% with 29 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/keys/keys.ts 70.58% 10 Missing ⚠️
src/revocation/crl.ts 91.89% 6 Missing ⚠️
src/revocation/chain.ts 25.00% 3 Missing ⚠️
src/x509/parse.ts 66.66% 3 Missing ⚠️
src/pkcs/pkcs7.ts 96.00% 2 Missing ⚠️
src/internal/crypto/pbes2.ts 75.00% 1 Missing ⚠️
src/internal/crypto/rsa-pss.ts 87.50% 1 Missing ⚠️
src/revocation/ocsp.ts 83.33% 1 Missing ⚠️
src/x509/extensions.ts 96.66% 1 Missing ⚠️
src/x509/name-text.ts 87.50% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@kjanat

This comment has been minimized.

@kjanat kjanat added cr:review Allow CodeRabbit review and removed cr:review Allow CodeRabbit review labels Jul 24, 2026
@kjanat
kjanat marked this pull request as draft July 25, 2026 02:51
@kjanat kjanat added the cr:review Allow CodeRabbit review label Jul 25, 2026
kjanat added 5 commits July 25, 2026 04:52
# Conflicts:
#	CHANGELOG.md
#	package.json
Reject malformed traditional PEM header names and accept the tagged
non-X.509 CertificateChoices CMS permits while rejecting unknown tags.

Correct related standards citations and replace the RFC fetch shell
snippet with a typed CLI that reports HTTP failures.
Expose every RFC 5652 CertificateChoices alternative instead of silently
dropping non-X.509 entries. Keep tagged DER for round-tripping and decode
the other-format OID so callers can distinguish mixed certificate sets.
Represent CMS signer identifiers, CRL distribution-point names, and
OCSP statuses as discriminated unions. Callers can narrow each wire
choice without handling impossible combinations of optional fields.
Fourteen switches over closed unions had no default, so a value from
outside the union fell off the end. Four were `assert*` helpers in
`keys.ts` returning void, where an unrecognized `algorithm.kind` made
the SPKI, PKCS#8, and JWK checks pass silently; the rest returned
`undefined` into WebCrypto, DER encoding, or a `Result`. Each now ends
in an `_exhaustive` default, which also turns a future variant into a
compile error.

`CreateSelfSignedCertificateInput` splits into a base and a key-source
union. `algorithm` was documented as ignored when `keyPair` is present;
supplying both no longer compiles.

`ParsedIssuingDistributionPoint` gains the scope union its builder input
already had, recording the RFC 5280 §5.2.5 at-most-one rule the parser
only enforced at runtime. An explicitly encoded FALSE stays distinct
from an omitted flag.
@kjanat
kjanat marked this pull request as ready for review July 25, 2026 09:19
@coderabbitai coderabbitai Bot added api Public API surface, types, exports, and reference documentation breaking-change Breaking API change bug Something isn't working documentation Improvements or additions to documentation pkcs PKCS#7 / PKCS#12 workflows rfc-conformance RFC adherence and conformance evidence tests Test coverage and harnesses labels Jul 25, 2026
coderabbitai[bot]

This comment was marked as resolved.

kjanat added 3 commits July 25, 2026 11:48
Disallow revocation-only fields on good and unknown OCSP builder
inputs, including structurally typed values that bypass excess-property
checks. Add compile-time coverage and document the exported type
contract migrations in the changelog.
Parse certificate choices through the bounded child iterator so a
malformed entry cannot consume bytes from the following SignedData
field. Cover the overrun and keep verification fixtures type-safe.
Exercise invalid runtime variants across key, extension, revocation, and
crypto helpers so closed-union fallthrough regressions fail explicitly.
@coderabbitai coderabbitai Bot removed the breaking-change Breaking API change label Jul 25, 2026
@coderabbitai coderabbitai Bot removed pkcs PKCS#7 / PKCS#12 workflows api Public API surface, types, exports, and reference documentation labels Jul 25, 2026
Enable differential verification during the coverage job so CI catches
behavioral divergence from OpenSSL on every test run.
@kjanat kjanat added breaking-change Breaking API change and removed cr:review Allow CodeRabbit review labels Jul 25, 2026
@kjanat kjanat changed the title fix(pem): OpenSSL header delimiter + audit citation sweep fix(pem)!: OpenSSL header delimiter + audit citation sweep Jul 25, 2026
coderabbitai[bot]

This comment was marked as resolved.

Check `revokedAt` and `revocationReasonCode` separately for good and
unknown statuses so either field becoming assignable fails the type suite.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Breaking API change bug Something isn't working documentation Improvements or additions to documentation rfc-conformance RFC adherence and conformance evidence tests Test coverage and harnesses

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant