@blamejs/core 0.15.14 → 0.15.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/x509-chain.js CHANGED
@@ -1,33 +1,80 @@
1
1
  "use strict";
2
+ /**
3
+ * @module b.x509Chain
4
+ * @nav Crypto
5
+ * @title X.509 chain (CA-bit issuer test)
6
+ *
7
+ * @intro
8
+ * The basicConstraints-enforcing issuer test the framework's own
9
+ * certificate-chain walkers route through (<code>b.tsa.verifyToken</code>,
10
+ * <code>b.mail.bimi</code> VMC/CMC, <code>b.mail.crypto.smime</code>,
11
+ * <code>b.mdoc</code>, <code>b.contentCredentials</code>,
12
+ * <code>b.auth.fido</code>). It exists because node:crypto's
13
+ * <code>X509Certificate.checkIssued()</code> validates the issuer/subject
14
+ * DN match, the AKI/SKI linkage, and — only when a keyUsage extension is
15
+ * present — keyCertSign, but it does <strong>not</strong> enforce
16
+ * basicConstraints cA:TRUE. A leaf / end-entity certificate (cA:FALSE)
17
+ * that omits keyUsage is therefore wrongly accepted as a signing CA for
18
+ * the next certificate in the chain — the classic basicConstraints bypass
19
+ * (CVE-2002-0862 class). Every in-tree walker routes its issuer test
20
+ * through these helpers so the cA enforcement can never be forgotten in
21
+ * one walker but present in another.
22
+ *
23
+ * Exposed so a consumer validating an X.509 chain <em>outside</em> a TLS
24
+ * handshake — an operator-uploaded CA bundle, a non-handshake PQ-signed
25
+ * certificate — has the same hardened, fail-closed test instead of being
26
+ * pushed toward the raw <code>checkIssued()</code> path this module
27
+ * exists to prevent. Both helpers fail closed: any malformed input or
28
+ * unsupported key type returns false rather than throwing.
29
+ *
30
+ * @card
31
+ * basicConstraints cA:TRUE-enforcing X.509 issuer test, fail-closed —
32
+ * the hardened alternative to node's checkIssued() for chains built
33
+ * outside a TLS handshake.
34
+ */
2
35
 
3
- // Internal X.509 path-validation helpers shared by the framework's
4
- // certificate-chain walkers (b.tsa.verifyToken, b.mail.bimi VMC/CMC,
5
- // b.mail.crypto.smime.verify). They exist because node:crypto's
6
- // X509Certificate.checkIssued() validates the issuer/subject DN match,
7
- // the AKI/SKI linkage, and — when a keyUsage extension is present —
8
- // keyCertSign, but it does NOT enforce basicConstraints cA:TRUE. A
9
- // leaf / end-entity certificate (cA:FALSE) that omits keyUsage is
10
- // therefore wrongly accepted as a signing CA for the next cert in the
11
- // chain the classic basicConstraints bypass (CVE-2002-0862 class).
12
- // Every chain walker routes its issuer test through these helpers so the
13
- // cA enforcement can never be forgotten in one walker but present in
14
- // another.
15
-
16
- // True only when `cert` asserts basicConstraints cA:TRUE. node's
17
- // X509Certificate exposes `.ca` (a boolean); a cert with no
18
- // basicConstraints extension or with cA:FALSE returns false. A missing
19
- // cert or a non-boolean `.ca` (parse failure / unsupported runtime)
20
- // fails closed.
36
+ /**
37
+ * @primitive b.x509Chain.isCaCert
38
+ * @signature b.x509Chain.isCaCert(cert)
39
+ * @since 0.15.15
40
+ * @status stable
41
+ * @related b.x509Chain.issuerValidlyIssued
42
+ *
43
+ * True only when <code>cert</code> asserts basicConstraints cA:TRUE.
44
+ * node's <code>X509Certificate</code> exposes <code>.ca</code> (a boolean);
45
+ * a certificate with no basicConstraints extension or with cA:FALSE
46
+ * returns false. A missing cert or a non-boolean <code>.ca</code> (parse
47
+ * failure / unsupported runtime) fails closed to false.
48
+ *
49
+ * @example
50
+ * var crypto = require("crypto");
51
+ * var ca = new crypto.X509Certificate(caPem);
52
+ * b.x509Chain.isCaCert(ca); // true only if basicConstraints cA:TRUE
53
+ */
21
54
  function isCaCert(cert) {
22
55
  return !!cert && cert.ca === true;
23
56
  }
24
57
 
25
- // True when `issuer` validly issued `subject` AND is itself a CA: the
26
- // DN / AKI-SKI / keyUsage linkage (checkIssued), the cryptographic
27
- // signature (verify), and basicConstraints cA:TRUE (isCaCert). The cA
28
- // check runs first so a non-CA cert is rejected before the expensive
29
- // signature verification. Any exception (malformed cert, unsupported
30
- // key type) fails closed to false.
58
+ /**
59
+ * @primitive b.x509Chain.issuerValidlyIssued
60
+ * @signature b.x509Chain.issuerValidlyIssued(issuer, subject)
61
+ * @since 0.15.15
62
+ * @status stable
63
+ * @related b.x509Chain.isCaCert
64
+ *
65
+ * True when <code>issuer</code> validly issued <code>subject</code> AND is
66
+ * itself a CA: the DN / AKI-SKI / keyUsage linkage (checkIssued), the
67
+ * cryptographic signature (verify), and basicConstraints cA:TRUE
68
+ * (isCaCert). The cA check runs first so a non-CA certificate is rejected
69
+ * before the expensive signature verification. Any exception (malformed
70
+ * cert, unsupported key type) fails closed to false.
71
+ *
72
+ * @example
73
+ * var crypto = require("crypto");
74
+ * var issuer = new crypto.X509Certificate(issuerPem);
75
+ * var subject = new crypto.X509Certificate(leafPem);
76
+ * b.x509Chain.issuerValidlyIssued(issuer, subject); // → boolean
77
+ */
31
78
  function issuerValidlyIssued(issuer, subject) {
32
79
  try {
33
80
  return isCaCert(issuer) &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.15.14",
3
+ "version": "0.15.15",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:81a205f2-938f-47e5-9426-3245e2ac5859",
5
+ "serialNumber": "urn:uuid:b3337d85-2941-4510-a9ff-2246e428aef5",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-06-21T13:24:58.132Z",
8
+ "timestamp": "2026-06-22T03:24:08.024Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "build"
@@ -19,14 +19,14 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@blamejs/core@0.15.14",
22
+ "bom-ref": "@blamejs/core@0.15.15",
23
23
  "type": "application",
24
24
  "name": "blamejs",
25
- "version": "0.15.14",
25
+ "version": "0.15.15",
26
26
  "scope": "required",
27
27
  "author": "blamejs contributors",
28
28
  "description": "The Node framework that owns its stack.",
29
- "purl": "pkg:npm/%40blamejs/core@0.15.14",
29
+ "purl": "pkg:npm/%40blamejs/core@0.15.15",
30
30
  "properties": [],
31
31
  "externalReferences": [
32
32
  {
@@ -54,7 +54,7 @@
54
54
  "components": [],
55
55
  "dependencies": [
56
56
  {
57
- "ref": "@blamejs/core@0.15.14",
57
+ "ref": "@blamejs/core@0.15.15",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]