@blamejs/pki 0.5.7 → 0.5.8

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.
Files changed (104) hide show
  1. package/CHANGELOG.md +405 -386
  2. package/MIGRATING.md +43 -0
  3. package/README.md +12 -12
  4. package/lib/acme.js +31 -31
  5. package/lib/asn1-der.js +10 -10
  6. package/lib/attrcert-sign.js +19 -19
  7. package/lib/byte-reader.js +6 -6
  8. package/lib/byte-writer.js +5 -5
  9. package/lib/cbor-det.js +27 -24
  10. package/lib/cmc-build.js +97 -92
  11. package/lib/cmc-verify.js +106 -30
  12. package/lib/cmp-build.js +25 -25
  13. package/lib/cmp-session.js +70 -70
  14. package/lib/cmp-verify.js +71 -57
  15. package/lib/cms-compress.js +7 -7
  16. package/lib/cms-decrypt.js +90 -72
  17. package/lib/cms-encrypt.js +32 -32
  18. package/lib/cms-sign.js +74 -55
  19. package/lib/cms-verify.js +97 -75
  20. package/lib/composite-sig.js +13 -13
  21. package/lib/constants.js +4 -4
  22. package/lib/crl-sign.js +22 -22
  23. package/lib/crl-verify.js +7 -6
  24. package/lib/crmf-sign.js +14 -14
  25. package/lib/csr-sign.js +8 -8
  26. package/lib/ct.js +37 -37
  27. package/lib/edwards-point.js +7 -7
  28. package/lib/est.js +98 -55
  29. package/lib/framework-error.js +5 -5
  30. package/lib/guard-all.js +3 -3
  31. package/lib/guard-async.js +4 -4
  32. package/lib/guard-bytes.js +79 -79
  33. package/lib/guard-compress.js +17 -17
  34. package/lib/guard-crypto.js +1 -1
  35. package/lib/guard-encoding.js +15 -15
  36. package/lib/guard-header.js +3 -3
  37. package/lib/guard-identifier.js +16 -16
  38. package/lib/guard-json.js +15 -15
  39. package/lib/guard-limits.js +7 -7
  40. package/lib/guard-name.js +81 -16
  41. package/lib/guard-parsed.js +80 -80
  42. package/lib/guard-range.js +19 -19
  43. package/lib/guard-secret.js +11 -10
  44. package/lib/guard-text.js +6 -6
  45. package/lib/guard-time.js +10 -10
  46. package/lib/hpke.js +18 -17
  47. package/lib/http-digest.js +35 -35
  48. package/lib/http-retry-after.js +13 -13
  49. package/lib/http-transport.js +20 -19
  50. package/lib/inspect.js +53 -53
  51. package/lib/ip-utils.js +2 -2
  52. package/lib/jose.js +13 -13
  53. package/lib/key.js +16 -16
  54. package/lib/lint.js +51 -51
  55. package/lib/merkle.js +51 -36
  56. package/lib/mime.js +18 -18
  57. package/lib/ocsp-verify.js +10 -10
  58. package/lib/ocsp.js +13 -13
  59. package/lib/oid.js +29 -29
  60. package/lib/path-validate.js +114 -113
  61. package/lib/pbes2.js +16 -16
  62. package/lib/pkcs12-build.js +53 -53
  63. package/lib/pki-build.js +21 -19
  64. package/lib/rc2.js +1 -1
  65. package/lib/rfc3339.js +5 -5
  66. package/lib/schema-all.js +31 -31
  67. package/lib/schema-attrcert.js +12 -12
  68. package/lib/schema-c509.js +144 -142
  69. package/lib/schema-cmc.js +58 -58
  70. package/lib/schema-cmp.js +43 -43
  71. package/lib/schema-cms.js +45 -45
  72. package/lib/schema-crl.js +7 -7
  73. package/lib/schema-crmf.js +28 -28
  74. package/lib/schema-csr.js +12 -12
  75. package/lib/schema-csrattrs.js +16 -16
  76. package/lib/schema-engine.js +18 -18
  77. package/lib/schema-ocsp.js +15 -15
  78. package/lib/schema-pkcs12.js +20 -20
  79. package/lib/schema-pkcs8.js +2 -2
  80. package/lib/schema-pkix.js +131 -126
  81. package/lib/schema-smime.js +19 -19
  82. package/lib/schema-tsp.js +12 -12
  83. package/lib/schema-x509.js +3 -3
  84. package/lib/shbs.js +18 -18
  85. package/lib/sign-scheme.js +13 -13
  86. package/lib/sigstore.js +10 -11
  87. package/lib/sleep.js +1 -1
  88. package/lib/smime.js +308 -96
  89. package/lib/tls-cert-compress.js +18 -18
  90. package/lib/trust.js +27 -27
  91. package/lib/tsp-sign.js +17 -17
  92. package/lib/validator-all.js +1 -1
  93. package/lib/validator-attcert.js +1 -1
  94. package/lib/validator-cose.js +43 -44
  95. package/lib/validator-keydesc.js +3 -3
  96. package/lib/validator-sig.js +13 -13
  97. package/lib/validator-tls.js +11 -11
  98. package/lib/validator-tpm.js +20 -19
  99. package/lib/webauthn-mds.js +66 -66
  100. package/lib/webauthn.js +33 -33
  101. package/lib/webcrypto.js +15 -15
  102. package/lib/x509-sign.js +13 -13
  103. package/package.json +3 -2
  104. package/sbom.cdx.json +6 -6
@@ -21,22 +21,22 @@ var async = require("./guard-async");
21
21
  // validation feeding a CWE-347-style verification-of-nothing). Always re-viewing
22
22
  // through Buffer.from(x.buffer, x.byteOffset, x.byteLength) turns the detached
23
23
  // read into a typed reject at the boundary. Size / length-field allocation
24
- // bounds (CWE-770 / CWE-400, the parser-DoS class) are NOT enforced here -- they
24
+ // bounds (CWE-770 / CWE-400, the parser-DoS class) are not enforced here. They
25
25
  // are per-format (a multi-MB CRL is legitimate, a Merkle proof is tiny), so they
26
26
  // live in guard-params and each decoder's own cap.
27
27
 
28
28
  // Choosing between `view` and `snapshot` at a boundary: a byte argument that is read only
29
- // during the synchronous pass that received it can be re-VIEWED, because nothing can run
30
- // between the check and the use. One that survives that pass -- stored in state, compared
31
- // after an await, embedded into output the verb assembles later -- must be SNAPSHOT, or the
29
+ // during the synchronous pass that received it can be re-viewed, because nothing can run
30
+ // between the check and the use. One that survives that pass (stored in state, compared
31
+ // after an await, embedded into output the verb assembles later) must be snapshotted, or the
32
32
  // caller can still rewrite the bytes after they were validated. The exceptions are the two
33
33
  // places holding a caller's SECRET, where a copy is the worse defect: a password or a private
34
34
  // key is re-viewed and left borrowed only when this module also clears the copy it made, so
35
35
  // no plaintext duplicate outlives the derivation.
36
36
 
37
37
  // The guard family threads a caller's typed error under two conventions: most guards take a
38
- // FACTORY (`E(code, message, cause)`, no `new`) because the engines that call them -- sign-scheme,
39
- // composite-sig, pki-build -- carry a bound factory that prefixes the caller's domain onto the
38
+ // FACTORY (`E(code, message, cause)`, no `new`) because the engines that call them (sign-scheme,
39
+ // composite-sig, pki-build) carry a bound factory that prefixes the caller's domain onto the
40
40
  // code; guard-bytes and guard-header take the error CLASS. A boundary that has only one of the two
41
41
  // would otherwise have to hand-roll the re-view to reach this guard at all, which is precisely what
42
42
  // the re-inline detector forbids, so accept either: a class (its prototype is an Error) is
@@ -64,12 +64,12 @@ function view(input, ErrorClass, code, label) {
64
64
 
65
65
  // source(input, ErrorClass, code, label) -> Buffer | throws ErrorClass
66
66
  // Accepts the full W3C BufferSource (Buffer / TypedArray view / raw ArrayBuffer)
67
- // -- the WebCrypto input contract. Re-VIEWS in every case, sharing the caller's
68
- // memory rather than taking a copy: `Buffer.from(arrayBuffer)` wraps the backing
67
+ // -- the WebCrypto input contract. Re-views in every case, sharing the caller's
68
+ // memory instead of taking a copy: `Buffer.from(arrayBuffer)` wraps the backing
69
69
  // store, it does not duplicate it. That is what makes this safe to call before a
70
- // size ceiling has been applied -- nothing is materialized -- and it is also why a
70
+ // size ceiling has been applied (nothing is materialized), and it is also why a
71
71
  // caller that must hold the bytes across an await wants `snapshotSource`, which
72
- // copies, rather than this. Throws on a detached backing store.
72
+ // copies. Throws on a detached backing store.
73
73
  // @enforced-by guard-shape-reinlined (the re-view shape is declared on view above)
74
74
  function source(input, ErrorClass, code, label) {
75
75
  var isAb = input instanceof ArrayBuffer;
@@ -88,15 +88,15 @@ function source(input, ErrorClass, code, label) {
88
88
  // The parse-then-verify time-of-check/time-of-use defence. A verification entry
89
89
  // point that PARSES its input synchronously and then VERIFIES a signature over
90
90
  // the same bytes in a later promise turn is reading the caller's memory twice
91
- // with an await in between. Every byte range the parse surfaced -- the signed
92
- // content, the signer set, the values the verdict is built from -- is a VIEW into
91
+ // with an await in between. Every byte range the parse surfaced (the signed
92
+ // content, the signer set, the values the verdict is built from) is a view into
93
93
  // that memory, so anything that rewrites the buffer in the gap makes the verdict
94
94
  // describe bytes other than the ones the signature was checked against
95
95
  // (CWE-367 TOCTOU reaching a CWE-347 wrong-verdict). The window is real without
96
96
  // an attacker in the process: a caller recycling a pooled read buffer across
97
97
  // concurrent verifies hits it by accident.
98
98
  //
99
- // So take one private copy at the boundary and read EVERYTHING from it. `view`
99
+ // So take one private copy at the boundary and read everything from it. `view`
100
100
  // re-views and is the right guard where the input is consumed in one synchronous
101
101
  // pass; this is its sibling for the boundary that spans an await.
102
102
  // @enforced-by behavioral -- a copy has no rename-proof code shape to detect (any
@@ -108,8 +108,8 @@ function snapshot(input, ErrorClass, code, label) {
108
108
  }
109
109
 
110
110
  // snapshotSource(input, ErrorClass, code, label) -> private Buffer copy | throws
111
- // The same parse-then-verify defence as `snapshot`, over the FULL W3C BufferSource
112
- // (raw ArrayBuffer / DataView / any typed-array view) rather than only the
111
+ // The same parse-then-verify defence as `snapshot`, over the whole W3C BufferSource
112
+ // (raw ArrayBuffer / DataView / any typed-array view) and not only the
113
113
  // Buffer / Uint8Array contract. A parser that accepts a BufferSource must snapshot
114
114
  // the same set: leaving an ArrayBuffer or a DataView aliased reopens the window for
115
115
  // exactly the inputs that took the wider path in.
@@ -121,25 +121,25 @@ function snapshotSource(input, ErrorClass, code, label) {
121
121
 
122
122
  // snapshotDeep(value, ErrorClass, code, label) -> a private copy of every byte leaf | throws
123
123
  //
124
- // `snapshot` closes the parse-then-verify window for ONE buffer. This closes it for a whole
125
- // caller-supplied SPEC -- the object a producing verb is handed and then reads across several
124
+ // `snapshot` closes the parse-then-verify window for one buffer. This closes it for a whole
125
+ // caller-supplied spec: the object a producing verb is handed and then reads across several
126
126
  // promise turns while it resolves a key, hashes, and signs. Every byte the verb ends up
127
127
  // encoding reaches it through some field of that object, and the caller still owns all of them,
128
128
  // so a spec validated at entry and read again after the first turn need not describe the same
129
129
  // certificate, CRL, or request. It is the same defect as an aliased buffer, one level up: the
130
130
  // value that passed the checks and the value that gets signed are two different reads.
131
131
  //
132
- // Copies byte views (through `snapshotSource`, so a detached backing store is refused rather
133
- // than copied as empty), arrays, dates, and PLAIN objects. Everything else -- a string, number,
134
- // bigint, boolean, a CryptoKey, any class instance -- is passed through by reference, because a
132
+ // Copies byte views (through `snapshotSource`, so a detached backing store is refused instead
133
+ // of copied as empty), arrays, dates, and plain objects. Everything else (a string, number,
134
+ // bigint, boolean, a CryptoKey, any class instance) is passed through by reference, because a
135
135
  // non-plain object is a platform or library handle whose identity is what makes it work; cloning
136
136
  // one would break it. `opts.maxDepth` bounds a cyclic or hostile structure; the cap is set far
137
137
  // above any real spec (the deepest is a certificate policy's UserNotice noticeRef, around 12).
138
138
  //
139
- // **A spec that carries SECRET material must pass `opts.collect`**, an array this fills with every
139
+ // A spec that carries secret material must pass `opts.collect`, an array this fills with every
140
140
  // buffer it copied. Copying a password or a private key produces a plaintext duplicate, and a
141
141
  // module whose ownership rules say "a caller's Buffer is borrowed, so leave it alone" will not
142
- // clear it -- the copy outlives the operation with no one accountable for it. Collect the copies
142
+ // clear it: the copy outlives the operation with no one accountable for it. Collect the copies
143
143
  // and zeroize them in a `finally`, so the fix for one defect does not open another.
144
144
  // @enforced-by behavioral -- a copy has no rename-proof code shape to detect (any `Buffer.from(x)`
145
145
  // is one). The guards are the RED vector that rewrites a field of the caller's spec after the
@@ -151,21 +151,21 @@ function snapshotDeep(value, ErrorClass, code, label, opts) {
151
151
  return _deep(value, ErrorClass, code, label, cap, 0, o.collect || null);
152
152
  }
153
153
 
154
- // Is this object a HANDLE -- something a copy would break rather than duplicate?
154
+ // Is this object a handle, meaning something a copy would break instead of duplicate?
155
155
  //
156
156
  // The line is not "does it have Object.prototype". A caller's own class instance used as an
157
157
  // options bag is data, and passing it through by reference on the strength of its prototype left
158
158
  // exactly the window this exists to close: `cms.sign` accepts any non-Buffer object as options, so
159
159
  // an instance whose `signedAttributes` flipped to false after the call still reached the signing
160
160
  // turn. What a copy genuinely breaks is an object whose meaning lives somewhere other than its own
161
- // properties -- a key handle, a live collection, a pending result. Those are named here rather than
161
+ // properties: a key handle, a live collection, a pending result. Those are named here, never
162
162
  // inferred, because inference gets it wrong in both directions: this engine's own CryptoKey carries
163
163
  // its Node key handle as an own property, so "has no own keys" would have copied it into a shell
164
164
  // that cannot sign, while a URL has none and would have copied into one that cannot be read.
165
- // isCryptoKeyLike is the toolkit's own answer to "is this a key handle" -- the same one key.js and
166
- // jose.js ask -- so a foreign implementation's CryptoKey is recognized here too.
167
- // The WebCrypto surface a CryptoKey presents, and nothing else. A real one -- this engine's, the
168
- // platform's, or another implementation's -- carries exactly these (its key material lives in an
165
+ // isCryptoKeyLike is the toolkit's own answer to "is this a key handle", the same one key.js and
166
+ // jose.js ask, so a foreign implementation's CryptoKey is recognized here too.
167
+ // The WebCrypto surface a CryptoKey presents, and nothing else. A real one (this engine's, the
168
+ // platform's, or another implementation's) carries exactly these (its key material lives in an
169
169
  // internal slot or a non-enumerable own property). A caller's options bag that happens to satisfy
170
170
  // the structural predicate carries its own fields alongside, and those are what give it away.
171
171
  var _CRYPTO_KEY_SURFACE = { type: 1, extractable: 1, algorithm: 1, usages: 1 };
@@ -181,9 +181,9 @@ var _THENABLE_SURFACE = { then: 1, catch: 1, finally: 1 };
181
181
  // Everything else is copied. Enumerating "handle shapes" to pass through was the wrong shape of
182
182
  // answer and lost repeatedly: every kind named as a handle turned out to be usable as an options
183
183
  // bag with fields glued on, and each new shape reopened the window for exactly the fields that
184
- // were glued on. There are only two honest outcomes for a caller's argument -- copy it, or refuse
185
- // it -- and this names the small set where copying is impossible, so the refusal below can be the
186
- // rule for all of them at once rather than a shape to be found later.
184
+ // were glued on. There are only two honest outcomes for a caller's argument: copy it, or refuse
185
+ // it. This names the small set where copying is impossible, so the refusal below can be the
186
+ // rule for all of them at once, never a shape to be found later.
187
187
  // The surface an opaque kind is defined by, or null when the value is not one of them. A plain
188
188
  // object literal is never opaque whatever it looks like: it is data this module can read and copy,
189
189
  // and isCryptoKeyLike is structural by design so a literal can wear the key shape.
@@ -194,8 +194,8 @@ function _opaqueSurface(v, ErrorClass, code, label) {
194
194
  if (v instanceof Error) return _ERROR_SURFACE;
195
195
  if (v instanceof RegExp) return _REGEXP_SURFACE;
196
196
  if (require("./webcrypto").isCryptoKeyLike(v)) return _CRYPTO_KEY_SURFACE; // allow:inline-require -- circular load: webcrypto requires this module
197
- // Asking whether it is a thenable READS a property, and a caller's accessor can throw -- the
198
- // same fault the copy itself types, so it is typed here too rather than escaping raw from a
197
+ // Asking whether it is a thenable reads a property, and a caller's accessor can throw: the
198
+ // same fault the copy itself types, so it is typed here too and never escapes raw from a
199
199
  // question this module asked on its own behalf.
200
200
  var then;
201
201
  try { then = v.then; }
@@ -204,17 +204,17 @@ function _opaqueSurface(v, ErrorClass, code, label) {
204
204
  return null;
205
205
  }
206
206
 
207
- // Is this opaque object safe to pass through -- carrying nothing beyond the surface its kind is
207
+ // Is this opaque object safe to pass through, carrying nothing beyond the surface its kind is
208
208
  // defined by? Anything more is the case with no safe answer: the object cannot be copied, and
209
209
  // passing it through would leave that data the caller's to change after the checks have read it.
210
- // Every reachable name is examined, not only the own ones -- a verb reads a field by name and does
210
+ // Every reachable name is examined, not only the own ones; a verb reads a field by name and does
211
211
  // not care where on the chain it sits.
212
212
  function _opaqueIsSafeToPass(v, surface) {
213
213
  var keys = _reachableKeys(v);
214
214
  for (var i = 0; i < keys.length; i++) {
215
215
  if (surface[keys[i]]) continue;
216
- // Only what the CALLER put there. An implementation's own internals are non-enumerable by
217
- // construction -- this engine's key handle, a platform object's slots -- and so are the methods
216
+ // Only what the caller put there. An implementation's own internals are non-enumerable by
217
+ // construction (this engine's key handle, a platform object's slots), and so are the methods
218
218
  // on any prototype, built-in or class-declared. What a caller adds, they add by assignment,
219
219
  // which is enumerable; that is the case the refusal is for, whatever the value's type. A
220
220
  // callable value is no exemption: an option is read for what it is, and `signedAttributes`
@@ -228,9 +228,9 @@ function _opaqueIsSafeToPass(v, surface) {
228
228
  // Every property name a `v.field` lookup could resolve: own and inherited, enumerable or not.
229
229
  //
230
230
  // The enumerable-only version of this was wrong three times running, each time in the same
231
- // direction -- own keys missed an inherited field, enumerable keys missed a non-enumerable one --
231
+ // direction (own keys missed an inherited field, enumerable keys missed a non-enumerable one),
232
232
  // and each miss left the caller's object reachable behind a copy that looked complete. A verb reads
233
- // an option BY NAME, so the set that has to be fixed is the set a name lookup can reach, and
233
+ // an option by name, so the set that has to be fixed is the set a name lookup can reach, and
234
234
  // nothing narrower. Object.prototype's own members are excluded: they are the language's, not the
235
235
  // caller's, and copying them onto every spec would shadow the prototype for no gain.
236
236
  function _reachableKeys(v) {
@@ -247,11 +247,11 @@ function _reachableKeys(v) {
247
247
  return names;
248
248
  }
249
249
 
250
- // A private copy of a byte value that is the SAME KIND as what the caller passed. The kind is
250
+ // A private copy of a byte value of the same kind the caller passed. The kind is
251
251
  // load-bearing: each verb's own field validators decide which byte forms that field accepts, and
252
252
  // most accept only Buffer / Uint8Array. Handing them a Buffer made from a DataView or a
253
- // Uint16Array would have those inputs quietly accepted -- reinterpreted through a platform's own
254
- // element layout -- where they were rejected before. Copying is not the place to decide what a
253
+ // Uint16Array would have those inputs quietly accepted, reinterpreted through a platform's own
254
+ // element layout, where they were rejected before. Copying is not the place to decide what a
255
255
  // field takes, so the copy preserves the type and the validator still sees what it was given.
256
256
  function _copyBytesSameKind(v, ErrorClass, code, label, collect) {
257
257
  var src = source(v, ErrorClass, code, label); // re-views; a detached backing store is refused
@@ -276,30 +276,30 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
276
276
  _copyNamed(v, bytesCopy, ErrorClass, code, label, cap, depth, collect);
277
277
  return bytesCopy;
278
278
  }
279
- // A parsed structure carrying guard-parsed's provenance record is a HANDLE: the record is keyed
279
+ // A parsed structure carrying guard-parsed's provenance record is a handle: the record is keyed
280
280
  // on the object's identity, so a copy of it carries none and every door that decides integrity
281
- // refuses the copy. It is also safe to leave alone -- that door re-derives from the bytes the
282
- // record names, so nothing done to the object since matters. That holds for it AS A PARSE
283
- // RESULT; a caller who adds an option to one and passes it where options are read by name has
284
- // added a field no door re-derives, so `AsProduced` is what is asked rather than `isRecorded`.
281
+ // refuses the copy. It is also safe to leave alone, since that door re-derives from the bytes the
282
+ // record names, so nothing done to the object since matters. That holds for it as a parse
283
+ // result; a caller who adds an option to one and passes it where options are read by name has
284
+ // added a field no door re-derives, so `AsProduced` is what is asked, not `isRecorded`.
285
285
  // Required inline because guard-parsed requires this module; at call time it is fully loaded.
286
286
  if (require("./guard-parsed").isRecordedAsProduced(v)) return v; // allow:inline-require -- circular load: guard-parsed requires this module
287
287
  if (v instanceof Date) return new Date(v.getTime());
288
288
  if (Array.isArray(v)) {
289
289
  var arr = [];
290
290
  for (var i = 0; i < v.length; i++) arr.push(_deep(v[i], ErrorClass, code, label, cap, depth + 1, collect));
291
- // An array can carry NAMED properties too, and a verb reads an option by name whatever the
291
+ // An array can carry named properties too, and a verb reads an option by name whatever the
292
292
  // argument's type: `opts = []; opts.pem = true` is an options object as far as `opts.pem` is
293
293
  // concerned. Copying only the indexed elements dropped those fields, which silently changed
294
- // what the verb was asked to do rather than failing.
294
+ // what the verb was asked to do instead of failing.
295
295
  _copyNamed(v, arr, ErrorClass, code, label, cap, depth, collect);
296
296
  return arr;
297
297
  }
298
298
  // The only kinds this module cannot read the state of. One carrying nothing of its own is passed
299
- // through -- there is no data on it to fix, and a copy would break it. One carrying its own
299
+ // through: there is no data on it to fix, and a copy would break it. One carrying its own
300
300
  // fields has no safe handling at all: it cannot be copied, and passing it through would leave
301
- // those fields the caller's to rewrite after the checks read them. That is refused rather than
302
- // half-handled, which is what keeps this from being another shape to be found later.
301
+ // those fields the caller's to rewrite after the checks read them. That case is refused outright,
302
+ // never half-handled, which is what keeps this from being another shape to be found later.
303
303
  var surface = _opaqueSurface(v, ErrorClass, code, label);
304
304
  if (surface) {
305
305
  if (_opaqueIsSafeToPass(v, surface)) return v;
@@ -309,10 +309,10 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
309
309
  }
310
310
  if (v instanceof Map) return _copyEntries(v, new Map(), ErrorClass, code, label, cap, depth, collect);
311
311
  if (v instanceof Set) return _copyEntries(v, new Set(), ErrorClass, code, label, cap, depth, collect);
312
- // The prototype is kept so an instance's methods still resolve. A null-prototype dictionary --
313
- // what `JSON.parse` or an explicit `Object.create(null)` produces -- must not come back
314
- // inheriting from Object.prototype either, which is why the prototype is carried across rather
315
- // than assumed.
312
+ // The prototype is kept so an instance's methods still resolve. A null-prototype dictionary
313
+ // (what `JSON.parse` or an explicit `Object.create(null)` produces) must not come back
314
+ // inheriting from Object.prototype either, which is why the prototype is carried across and
315
+ // never assumed.
316
316
  var out = Object.create(Object.getPrototypeOf(v));
317
317
  _copyNamed(v, out, ErrorClass, code, label, cap, depth, collect);
318
318
  return out;
@@ -320,13 +320,13 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect) {
320
320
 
321
321
  // Which names to carry across, given what the copy is.
322
322
  //
323
- // For a plain object or a class instance -- the shapes an options bag actually takes -- it is every
323
+ // For a plain object or a class instance (the shapes an options bag actually takes) it is every
324
324
  // name a lookup could resolve, inherited included, because that is what the verb reads.
325
325
  //
326
- // For an array, a byte view, a Map or a Set, it is the caller's OWN added names only. Their
327
- // prototypes are full of accessors that describe the kind rather than the caller (`length`,
326
+ // For an array, a byte view, a Map or a Set, it is the caller's own added names only. Their
327
+ // prototypes are full of accessors that describe the kind, not the caller (`length`,
328
328
  // `buffer`, `size`, and Node's `parent`, which hands back the 64 KiB arena a small Buffer was
329
- // allocated from) -- every one of those is already correct on the copy, and reading them would
329
+ // allocated from). Every one of those is already correct on the copy, and reading them would
330
330
  // copy things the caller never passed. Enumerating the accessors to skip is the wrong way round;
331
331
  // what the caller added is exactly what is own and not an index.
332
332
  function _namesToCopy(src, dst) {
@@ -343,7 +343,7 @@ function _namesToCopy(src, dst) {
343
343
  }
344
344
 
345
345
  // A Map or a Set is data the caller can still change, entry by entry, so it is copied like any
346
- // other -- entries first, then the named properties one can carry alongside them.
346
+ // other: entries first, then the named properties one can carry alongside them.
347
347
  function _copyEntries(src, dst, ErrorClass, code, label, cap, depth, collect) {
348
348
  src.forEach(function (value, key) {
349
349
  var copiedValue = _deep(value, ErrorClass, code, label, cap, depth + 1, collect);
@@ -354,25 +354,25 @@ function _copyEntries(src, dst, ErrorClass, code, label, cap, depth, collect) {
354
354
  return dst;
355
355
  }
356
356
 
357
- // Copy every value a name lookup on `src` could reach onto `dst`, as an OWN data property.
357
+ // Copy every value a name lookup on `src` could reach onto `dst`, as an own data property.
358
358
  //
359
359
  // Own matters: a key literally named `__proto__` would otherwise re-point `dst`, so the field the
360
360
  // caller passed disappears from Object.keys and an unknown-option check walks a different object
361
- // than the verb goes on to read. Shadowing matters for the same reason it is done at all -- an own
361
+ // than the verb goes on to read. Shadowing matters for the same reason it is done at all: an own
362
362
  // copy is what makes an inherited value stop tracking the caller's prototype. A method is left
363
- // where it is: copying a function would only move it, and it is the prototype's behaviour rather
364
- // than the caller's data.
363
+ // where it is, since copying a function would only move it, and it is the prototype's behaviour,
364
+ // not the caller's data.
365
365
  function _copyNamed(src, dst, ErrorClass, code, label, cap, depth, collect) {
366
366
  var keys = _namesToCopy(src, dst);
367
367
  for (var k = 0; k < keys.length; k++) {
368
368
  var value;
369
369
  // Reading a caller's property can run a caller's accessor, and one that throws is a bad input
370
- // like any other -- the fault gets this boundary's typed code with the raw error as its cause,
371
- // rather than escaping as itself from inside a verb the caller called for something else.
370
+ // like any other: the fault gets this boundary's typed code with the raw error as its cause,
371
+ // and never escapes as itself from inside a verb the caller called for something else.
372
372
  try { value = src[keys[k]]; }
373
373
  catch (e) { throw _raise(ErrorClass, code, label + ": reading " + JSON.stringify(keys[k]) + " threw", e); }
374
- // A function is carried across by reference rather than copied -- there is nothing in it to
375
- // copy -- but it is still carried. Dropping it changed what the caller passed: an unknown spec
374
+ // A function is carried across by reference, since there is nothing in it to copy, but it is
375
+ // still carried. Dropping it changed what the caller passed: an unknown spec
376
376
  // field whose value happened to be a function stopped reaching the verb's own key check, so a
377
377
  // typo that used to be refused was silently accepted.
378
378
  Object.defineProperty(dst, keys[k], {
@@ -396,17 +396,17 @@ function _wasEnumerable(v, name) {
396
396
  // fixArguments(ErrorClass, code, args) -> { values, release }
397
397
  //
398
398
  // The whole rule for a verb that spans a promise turn, in one call. `args` is a list of
399
- // `[value, label]` pairs -- every argument the verb was handed. Each is deep-copied, so no field
399
+ // `[value, label]` pairs, one per argument the verb was handed. Each is deep-copied, so no field
400
400
  // of any of them, at any depth, is still the caller's to change once the verb has begun; `release`
401
401
  // clears every copy that was made and belongs in a `finally`, so a copied password or private key
402
402
  // does not outlive the call.
403
403
  //
404
404
  // Both halves are needed and neither is optional. Copying only the argument that looks like data
405
- // leaves a secret nested inside the one that looks like a handle -- `opts.mac.secret` sitting a
406
- // level below a shallow copy -- readable and rewritable across the turn. Copying without releasing
405
+ // leaves a secret nested inside the one that looks like a handle (`opts.mac.secret` sitting a
406
+ // level below a shallow copy) readable and rewritable across the turn. Copying without releasing
407
407
  // answers that by duplicating the secret instead. Deciding per field which is which is the judgment
408
408
  // that keeps going wrong, so there is no per-field decision here: everything is copied, everything
409
- // copied is cleared, and the only things left alone are the ones a copy would BREAK -- a CryptoKey
409
+ // copied is cleared, and the only things left alone are the ones a copy would break: a CryptoKey
410
410
  // or any class instance (its identity is what makes it work) and a recorded parse result (its
411
411
  // provenance is keyed to the object).
412
412
  // @enforced-by behavioral -- there is no rename-proof code shape for "copied every argument". The
@@ -415,7 +415,7 @@ function _wasEnumerable(v, name) {
415
415
  function fixArguments(ErrorClass, code, args) {
416
416
  var copies = [];
417
417
  var values = [];
418
- // Through guard.secret, which owns what clearing a secret means -- required inline because
418
+ // Through guard.secret, which owns what clearing a secret means. Required inline because
419
419
  // guard-secret requires this module; at call time it is fully loaded.
420
420
  function release() {
421
421
  require("./guard-secret").zeroizeAll(copies, ErrorClass, code, // allow:inline-require -- circular load: guard-secret requires this module
@@ -426,8 +426,8 @@ function fixArguments(ErrorClass, code, args) {
426
426
  values.push(snapshotDeep(args[i][0], ErrorClass, code, args[i][1], { collect: copies }));
427
427
  }
428
428
  } catch (e) {
429
- // The copying itself can fail partway -- a detached leaf, a structure past the depth cap, a
430
- // getter that throws -- and the arguments already copied by then are just as much ours as if
429
+ // The copying itself can fail partway (a detached leaf, a structure past the depth cap, a
430
+ // getter that throws), and the arguments already copied by then are just as much ours as if
431
431
  // the call had gone on to succeed. Returning nothing would leave the caller with no handle to
432
432
  // release them, so a signer key or a password copied before the fault would stay readable for
433
433
  // as long as the heap held it. Clear what was made, then let the fault out unchanged.
@@ -440,9 +440,9 @@ function fixArguments(ErrorClass, code, args) {
440
440
  // fixedCall(ErrorClass, code, args, body) -> Promise
441
441
  //
442
442
  // The form every Promise-returning producing verb uses, because the halves have to be arranged in
443
- // exactly one way and this is it. The copy runs INSIDE guard-async's boundary, so a fault in the
444
- // copy itself -- a detached view, a structure nested past the cap, a getter that throws -- leaves
445
- // as a REJECTION like every other fault of a verb documented `-> Promise<...>`, rather than as a
443
+ // exactly one way and this is it. The copy runs inside guard-async's boundary, so a fault in the
444
+ // copy itself (a detached view, a structure nested past the cap, a getter that throws) leaves
445
+ // as a rejection like every other fault of a verb documented `-> Promise<...>`, never as a
446
446
  // synchronous throw past the caller's `.catch`. It still runs at the call, before any turn passes,
447
447
  // which is what fixes the arguments. And the release runs whether the body resolved, rejected, or
448
448
  // never ran, so a copied secret is cleared on every path out.
@@ -28,7 +28,7 @@
28
28
  // `info: true`, each raises ERR_BUFFER_TOO_LARGE on a cap breach, and each
29
29
  // accepts trailing bytes when left unchecked.
30
30
  //
31
- // E is the caller's (code, message, cause) typed-error FACTORY -- never an error
31
+ // E is the caller's (code, message, cause) typed-error factory, never an error
32
32
  // class. Passing a class here crashes on the error path ("class cannot be invoked
33
33
  // without new"), which converts a rejection into a fail-open. `codes` names the
34
34
  // two verdicts a caller distinguishes: `tooLarge` when the output would exceed
@@ -45,8 +45,8 @@ var DECOMPRESS = {
45
45
  zstd: zlib.zstdDecompressSync, // RFC 8478
46
46
  };
47
47
 
48
- // The compressors, used ONLY by the truncation probe below. Producing a compressed stream is
49
- // not the guarded shape -- decompressing an untrusted one is.
48
+ // The compressors, used only by the truncation probe below. Producing a compressed stream is
49
+ // not the guarded shape; decompressing an untrusted one is.
50
50
  var _PROBE_COMPRESS = {
51
51
  zlib: zlib.deflateSync,
52
52
  brotli: zlib.brotliCompressSync,
@@ -55,22 +55,22 @@ var _PROBE_COMPRESS = {
55
55
 
56
56
  // A decompressor must REPORT a frame it could not finish. Not all of them do: on some supported
57
57
  // runtimes the zstd binding returns a SHORT (often empty) result for a truncated frame instead
58
- // of faulting, and reports the entire input as consumed -- so neither the returned bytes nor the
58
+ // of faulting, and reports the entire input as consumed, so neither the returned bytes nor the
59
59
  // consumed-length check below can see that the frame was cut. That is a silent truncation: a peer
60
60
  // strips a frame's tail and the receiver processes a prefix as though it were the whole message.
61
61
  //
62
62
  // An algorithm whose runtime cannot report this cannot be decompressed safely here, so it is
63
- // dropped from the advertised set at load rather than accepted with a defect. Consumers build
63
+ // dropped from the advertised set at load instead of accepted with a defect. Consumers build
64
64
  // their wire registries by intersecting with algorithms(), so a protocol simply does not offer
65
65
  // or accept it, and it returns on its own once the runtime reports truncation.
66
- // Nothing here is enabled by an exception alone: an algorithm qualifies only by POSITIVE proof
67
- // that a whole frame round-trips AND that a cut frame is refused. Every other outcome -- a
68
- // missing function, a compressor fault, a wrong round-trip, an unrelated error -- leaves it out.
66
+ // Nothing here is enabled by an exception alone: an algorithm qualifies only by positive proof
67
+ // that a whole frame round-trips and that a cut frame is refused. Every other outcome (a
68
+ // missing function, a compressor fault, a wrong round-trip, an unrelated error) leaves it out.
69
69
  //
70
70
  // Coverage residual: the early-return branches are reachable only on a runtime whose own
71
71
  // compression library is broken (a missing export, a compressor that throws on 46 ASCII bytes, a
72
72
  // round-trip that does not reproduce its input). The tables are captured at module load, so those
73
- // states cannot be induced from a test without replacing node:zlib beforehand -- and forcing them
73
+ // states cannot be induced from a test without replacing node:zlib beforehand, and forcing them
74
74
  // would assert nothing about the property this function exists to establish. They stay because
75
75
  // their absence is what would make a broken runtime silently qualify an algorithm.
76
76
  function _reportsTruncation(name) {
@@ -82,13 +82,13 @@ function _reportsTruncation(name) {
82
82
  try { frame = compress(sample); }
83
83
  catch (_e) { /* allow:swallow-unverified a compressor that cannot compress 46 ASCII bytes is a broken runtime; the algorithm simply does not qualify, which is the fail-closed direction */ return false; }
84
84
  // A cut of 2 removes the frame's end marker; the sample is long enough that what remains is
85
- // still a plausible frame head rather than nothing at all.
85
+ // still a plausible frame head and not nothing at all.
86
86
  if (!Buffer.isBuffer(frame) || frame.length < 4) return false;
87
87
  try { whole = decompress(frame, { maxOutputLength: 4096 }); }
88
88
  catch (_e2) { /* allow:swallow-unverified a decompressor that rejects its own compressor's whole frame is a broken runtime; the algorithm does not qualify, again fail-closed */ return false; }
89
89
  if (!Buffer.isBuffer(whole) || !whole.equals(sample)) return false;
90
- // The cut frame must be REFUSED. A returned value of any length -- including the empty buffer
91
- // some bindings hand back -- means a truncation would pass through unseen.
90
+ // The cut frame must be refused. A returned value of any length, including the empty buffer
91
+ // some bindings hand back, means a truncation would pass through unseen.
92
92
  var cutAccepted = false;
93
93
  try {
94
94
  decompress(frame.subarray(0, frame.length - 2), { maxOutputLength: 4096 });
@@ -115,7 +115,7 @@ function bounded(algorithm, stream, cap, E, codes, label) {
115
115
  // An unknown algorithm -- or one this runtime cannot decompress safely -- is an authoring
116
116
  // fault, not untrusted input: a caller resolves a wire value to a name against algorithms()
117
117
  // and rejects one it does not find, before reaching here. Arriving with a name outside that
118
- // set means the consumer skipped the step, so it faults loudly rather than silently.
118
+ // set means the consumer skipped the step, so it faults loudly and never silently.
119
119
  if (!Object.prototype.hasOwnProperty.call(SAFE, algorithm) || !decompress) {
120
120
  throw new TypeError("guard.compress.bounded: unknown or unsafe algorithm " + JSON.stringify(algorithm));
121
121
  }
@@ -127,7 +127,7 @@ function bounded(algorithm, stream, cap, E, codes, label) {
127
127
  // The ceiling is an authoring input: an undefined / NaN / fractional / negative
128
128
  // cap would silently disable the bomb defence. It must also be at least 1 --
129
129
  // node rejects maxOutputLength 0 with a different fault than a cap breach, so a
130
- // zero cap would surface as a malformed-stream verdict rather than a config error.
130
+ // zero cap would surface as a malformed-stream verdict instead of a config error.
131
131
  if (!Number.isInteger(cap) || cap < 1) {
132
132
  throw new TypeError("guard.compress.bounded: cap must be a positive integer");
133
133
  }
@@ -142,8 +142,8 @@ function bounded(algorithm, stream, cap, E, codes, label) {
142
142
  throw E(codes.failed, what + " could not be decompressed", e);
143
143
  }
144
144
  // `bytesWritten` is the count of INPUT bytes the engine consumed. A frame that
145
- // ends before the input does means the remainder was ignored -- the malleability
146
- // above -- so the whole input must be exactly one frame.
145
+ // ends before the input does means the remainder was ignored, which is the
146
+ // malleability above, so the whole input must be exactly one frame.
147
147
  var consumed = res.engine.bytesWritten;
148
148
  if (consumed !== stream.length) {
149
149
  throw E(codes.failed, what + " carries " + (stream.length - consumed) +
@@ -152,7 +152,7 @@ function bounded(algorithm, stream, cap, E, codes, label) {
152
152
  return res.buffer;
153
153
  }
154
154
 
155
- // The algorithm names this guard can decompress SAFELY on this runtime -- the registry
155
+ // The algorithm names this guard can decompress safely on this runtime: the registry
156
156
  // minus any whose decompressor cannot report an unfinished frame. A consumer intersects
157
157
  // its protocol's algorithm registry with this, so it never advertises or accepts something
158
158
  // it could not refuse a truncation of.
@@ -25,7 +25,7 @@
25
25
  // MAC / digest BIT STRING with a non-zero unused-bits count is not whole octets,
26
26
  // so trailing sub-octet bits let two encodings carry "one" signature. Every RFC
27
27
  // 9481/4211/6960/5280 signature output is a whole number of octets, so a value
28
- // with unusedBits !== 0 fails closed BEFORE its bytes reach a verifier.
28
+ // with unusedBits !== 0 fails closed before its bytes reach a verifier.
29
29
 
30
30
  var nodeCrypto = require("node:crypto");
31
31
 
@@ -10,28 +10,28 @@
10
10
  // guard-encoding -- strict decode of an untrusted base64 / base64url / hex text
11
11
  // to bytes. Node's Buffer.from(x, "base64"|"base64url"|"hex") is LENIENT: it
12
12
  // silently drops the first invalid character (and everything after a stray one),
13
- // accepts non-canonical trailing bits, and tolerates missing/extra padding, so
14
- // two distinct texts alias one byte string -- or a malformed text decodes to a
15
- // SHORTER, different value than intended. And it allocates the whole decode
16
- // before any size is checked. This is CWE-172 (encoding-transformation error) /
13
+ // accepts non-canonical trailing bits, and tolerates missing/extra padding. Two
14
+ // distinct texts can therefore alias one byte string, and a malformed text can
15
+ // decode to a shorter, different value than intended. And it allocates the whole
16
+ // decode before any size is checked. This is CWE-172 (encoding-transformation error) /
17
17
  // CWE-20 (canonicalization malleability) + CWE-770 (allocate-before-cap): RFC
18
18
  // 4648 sec. 3.5 / sec. 5 and RFC 8555 sec. 6.1 require the UNIQUE canonical
19
19
  // encoding. Each decoder here gates the alphabet, rejects an impossible length,
20
- // enforces the byte cap BEFORE the copy, decodes, and verifies canonicality by a
21
- // re-encode round-trip -- so a value that is not the one canonical encoding of
20
+ // enforces the byte cap before the copy, decodes, and verifies canonicality by a
21
+ // re-encode round-trip, so a value that is not the one canonical encoding of
22
22
  // its bytes fails closed with the caller's typed error.
23
23
  //
24
24
  // E is the caller's (code, message) typed-error factory; `code` the frozen
25
25
  // domain/reason; `label` the field phrase; `maxBytes` an optional decoded-size
26
26
  // cap (null/undefined = uncapped, for a PEM cert body already bounded upstream).
27
27
 
28
- // The alphabets are TABLES, walked one character at a time, rather than regular
29
- // expressions. A guard runs on the most hostile input the toolkit sees, and a
30
- // pattern engine's cost on a non-matching string is a property of the pattern
31
- // rather than of the length -- the one thing a bound cannot be placed on from the
32
- // outside. A table lookup is one array index per character and its cost is the
33
- // length, which the caller already caps. It is also the more honest statement of
34
- // the rule: the set of permitted characters IS the rule, written out.
28
+ // The alphabets are tables, walked one character at a time. Regular expressions
29
+ // would be the obvious alternative, but a guard runs on the most hostile input
30
+ // the toolkit sees, and a pattern engine's cost on a non-matching string is
31
+ // decided by the pattern, which is the one thing a bound cannot be placed on from
32
+ // the outside. A table lookup is one array index per character, so its cost
33
+ // follows the length, which the caller already caps. It is also the more honest
34
+ // statement of the rule: the set of permitted characters is the rule, written out.
35
35
  function _alphabet(chars) {
36
36
  var t = new Uint8Array(128);
37
37
  for (var i = 0; i < chars.length; i++) t[chars.charCodeAt(i)] = 1;
@@ -43,8 +43,8 @@ var B64_ALPHABET = _alphabet(UPPER + LOWER + DIGITS + "+/");
43
43
  var HEX_ALPHABET = _alphabet(DIGITS + "abcdef" + "ABCDEF");
44
44
 
45
45
  // Every character of `text` is in `table`. A code point outside Latin-1's low half
46
- // (including every astral half) is outside all three alphabets, so the table bound
47
- // is the reject rather than an index that reads undefined.
46
+ // (including every astral half) is outside all three alphabets, and the explicit
47
+ // bound rejects it, so no lookup can read undefined off the end of the table.
48
48
  function _inAlphabet(text, table) {
49
49
  for (var i = 0; i < text.length; i++) {
50
50
  var c = text.charCodeAt(i);
@@ -20,9 +20,9 @@
20
20
  var C = require("./constants");
21
21
 
22
22
  // assertField(name, value, E, code) -> value | throws new E(code, ...)
23
- // name: RFC 5322 ftext -- printable ASCII [0x21, 0x7e] except ':' (0x3a), non-empty
23
+ // name: RFC 5322 ftext, printable ASCII [0x21, 0x7e] except ':' (0x3a), non-empty
24
24
  // (a space, control byte, or ':' in a field name breaks the "Name: value" grammar).
25
- // value: reject CR (0x0d) / LF (0x0a) / NUL (0x00) -- the injection bytes; TAB
25
+ // value: reject CR (0x0d), LF (0x0a) and NUL (0x00), the injection bytes; TAB
26
26
  // (0x09, folding whitespace) and printable non-ASCII (a UTF-8 header value, RFC
27
27
  // 6532) pass. E is the caller's typed-error CLASS, thrown `new E(code, message)`
28
28
  // -- the same convention lib/mime.js (this guard's caller) and guard.bytes/text use.
@@ -42,7 +42,7 @@ function assertField(name, value, E, code) {
42
42
  if (vc === 0x00 || vc === 0x0d || vc === 0x0a) throw new E(code, "a header field value must not contain CR / LF / NUL (header injection) in " + JSON.stringify(name));
43
43
  }
44
44
  // RFC 5322 sec. 2.1.1: the serialized "Name: value" line (UTF-8 octets, excluding CRLF) must not exceed
45
- // the line limit, or a relay may re-fold it -- silently changing the signed bytes of a protected header.
45
+ // the line limit, or a relay may re-fold it and silently change the signed bytes of a protected header.
46
46
  if (Buffer.byteLength(name, "utf8") + 2 + Buffer.byteLength(v, "utf8") > C.LIMITS.HEADER_LINE_MAX_OCTETS) {
47
47
  throw new E(code, "a header field line exceeds RFC 5322's " + C.LIMITS.HEADER_LINE_MAX_OCTETS + "-octet limit: " + JSON.stringify(name));
48
48
  }