@blamejs/pki 0.6.13 → 0.6.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/CHANGELOG.md +22 -1
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/acme.js +59 -815
- package/lib/asn1-der.js +7 -245
- package/lib/attrcert-sign.js +12 -260
- package/lib/attrcert-verify.js +1 -7
- package/lib/byte-reader.js +0 -8
- package/lib/byte-writer.js +0 -11
- package/lib/cbor-det.js +0 -54
- package/lib/cmc-build.js +15 -357
- package/lib/cmc-verify.js +6 -239
- package/lib/cmp-build.js +41 -317
- package/lib/cmp-session.js +73 -760
- package/lib/cmp-verify.js +32 -488
- package/lib/cms-compress.js +3 -32
- package/lib/cms-decrypt.js +29 -294
- package/lib/cms-encrypt.js +14 -234
- package/lib/cms-sign.js +29 -324
- package/lib/cms-verify.js +9 -500
- package/lib/composite-kem.js +2 -102
- package/lib/composite-sig.js +1 -77
- package/lib/constants.js +0 -249
- package/lib/crl-sign.js +9 -237
- package/lib/crl-verify.js +1 -10
- package/lib/crmf-sign.js +19 -198
- package/lib/crmf-verify.js +1 -12
- package/lib/csr-sign.js +3 -34
- package/lib/csr-verify.js +1 -12
- package/lib/ct.js +28 -253
- package/lib/edwards-point.js +10 -44
- package/lib/est.js +28 -764
- package/lib/framework-error.js +4 -182
- package/lib/guard-all.js +1 -58
- package/lib/guard-async.js +1 -36
- package/lib/guard-bytes.js +6 -650
- package/lib/guard-compress.js +5 -102
- package/lib/guard-crypto.js +1 -40
- package/lib/guard-der.js +2 -93
- package/lib/guard-encoding.js +2 -60
- package/lib/guard-header.js +1 -36
- package/lib/guard-identifier.js +7 -531
- package/lib/guard-intrinsic.js +1 -150
- package/lib/guard-json.js +10 -73
- package/lib/guard-limits.js +1 -77
- package/lib/guard-list.js +1 -49
- package/lib/guard-name.js +3 -209
- package/lib/guard-parsed.js +7 -335
- package/lib/guard-range.js +1 -71
- package/lib/guard-secret.js +1 -102
- package/lib/guard-text.js +1 -64
- package/lib/guard-time.js +1 -97
- package/lib/hpke.js +3 -105
- package/lib/http-digest.js +14 -142
- package/lib/http-retry-after.js +1 -47
- package/lib/http-transport.js +21 -131
- package/lib/inspect.js +30 -284
- package/lib/ip-utils.js +6 -47
- package/lib/jose.js +7 -142
- package/lib/key.js +2 -67
- package/lib/lint.js +9 -194
- package/lib/merkle.js +1 -27
- package/lib/mime.js +9 -82
- package/lib/ocsp-request-verify.js +1 -14
- package/lib/ocsp-verify.js +1 -82
- package/lib/ocsp.js +11 -169
- package/lib/oid.js +5 -337
- package/lib/path-validate.js +103 -1492
- package/lib/pbes2.js +2 -89
- package/lib/pkcs12-build.js +31 -379
- package/lib/pki-build.js +64 -290
- package/lib/rc2.js +2 -18
- package/lib/rfc3339.js +4 -27
- package/lib/scep.js +59 -233
- package/lib/schema-all.js +0 -122
- package/lib/schema-attrcert.js +4 -146
- package/lib/schema-c509.js +153 -802
- package/lib/schema-cmc.js +5 -220
- package/lib/schema-cmp.js +2 -223
- package/lib/schema-cms.js +13 -427
- package/lib/schema-crl.js +5 -68
- package/lib/schema-crmf.js +6 -167
- package/lib/schema-csr.js +1 -54
- package/lib/schema-csrattrs.js +2 -87
- package/lib/schema-engine.js +0 -152
- package/lib/schema-ocsp.js +0 -117
- package/lib/schema-pkcs12.js +2 -93
- package/lib/schema-pkcs8.js +3 -35
- package/lib/schema-pkix.js +24 -655
- package/lib/schema-smime.js +0 -54
- package/lib/schema-tsp.js +3 -99
- package/lib/schema-x509.js +4 -63
- package/lib/shbs.js +11 -95
- package/lib/sign-scheme.js +2 -97
- package/lib/sigstore.js +9 -169
- package/lib/sleep.js +2 -8
- package/lib/smime.js +15 -408
- package/lib/tls-cert-compress.js +0 -62
- package/lib/trust.js +19 -185
- package/lib/tsp-sign.js +16 -270
- package/lib/validator-all.js +1 -30
- package/lib/validator-attcert.js +2 -46
- package/lib/validator-cose.js +2 -153
- package/lib/validator-keydesc.js +1 -37
- package/lib/validator-sig.js +1 -46
- package/lib/validator-tls.js +1 -88
- package/lib/validator-tpm.js +19 -122
- package/lib/verify-seam.js +1 -24
- package/lib/webauthn-mds.js +3 -400
- package/lib/webauthn.js +12 -833
- package/lib/webcrypto.js +5 -485
- package/lib/x509-sign.js +4 -108
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/guard-intrinsic.js
CHANGED
|
@@ -1,78 +1,25 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) blamejs contributors
|
|
3
3
|
"use strict";
|
|
4
|
-
//
|
|
5
|
-
// @internal -- no operator-facing namespace. The documented surface is every guard that composes
|
|
6
|
-
// this one, which is every guard that performs its work with a captured intrinsic: guard-bytes
|
|
7
|
-
// (the byte-source door), guard-time (the evaluation instant), guard-name (distinguished-name
|
|
8
|
-
// identity), guard-text (the byte-to-string decode), guard-secret (the wipe).
|
|
9
|
-
//
|
|
10
|
-
// guard-intrinsic -- invoke a captured method against a receiver without reading any property of
|
|
11
|
-
// the captured function.
|
|
12
|
-
//
|
|
13
|
-
// Capturing a method at module load closes half of the hole. `var _fill =
|
|
14
|
-
// Uint8Array.prototype.fill` freezes which function the guard will run, so a later
|
|
15
|
-
// `Uint8Array.prototype.fill = noop` changes nothing. Then `_fill.call(view, 0)` reads `call` off
|
|
16
|
-
// that function object, and the object is the one still sitting on the prototype where any caller
|
|
17
|
-
// can reach it. Assigning `Uint8Array.prototype.fill.call = function () {}` installs an own
|
|
18
|
-
// property that shadows `Function.prototype.call`, and the guard runs the caller's function with
|
|
19
|
-
// the same result the un-captured code had. The wipe clears nothing. A distinguished name compares
|
|
20
|
-
// equal to an unrelated one. A decode returns a string the caller chose. Every check around it
|
|
21
|
-
// still runs and still passes.
|
|
22
|
-
//
|
|
23
|
-
// The uncurried form performs no property read at the call site. `_fill(view, 0)` invokes a
|
|
24
|
-
// function object no caller holds a reference to, so nothing on it is left to poison. The binding
|
|
25
|
-
// happens here, at load, while `Function.prototype.call` and `.bind` are still the language's own.
|
|
26
|
-
//
|
|
27
|
-
// The scope of the defense is replacement that happens after this module loads. Code running
|
|
28
|
-
// before it is already inside the trust boundary and can reach further than any single method, so
|
|
29
|
-
// there is no defense here to add for that case. What capture-then-uncurry buys is that a caller
|
|
30
|
-
// who receives control later, through an option accessor or while a verb is suspended on an await,
|
|
31
|
-
// cannot change what a guard does.
|
|
4
|
+
// @internal
|
|
32
5
|
|
|
33
6
|
var _utilTypes = require("util").types;
|
|
34
7
|
|
|
35
8
|
var _call = Function.prototype.call;
|
|
36
9
|
var _bind = Function.prototype.bind;
|
|
37
|
-
// The invocation primitive `uncurry` itself is built out of. Binding as `_bind.call(_call, fn)`
|
|
38
|
-
// would read `call` off the captured bind function, which is the very shape this module exists to
|
|
39
|
-
// remove -- and `uncurry` is exported, so it can run long after load, while another guard
|
|
40
|
-
// initializes. `Reflect.apply` is invoked directly, so no property of it is consulted either.
|
|
41
10
|
var _reflectApply = Reflect.apply;
|
|
42
11
|
|
|
43
|
-
// isArray -- the array test, snapshotted for the same reason as the predicates below. It decides
|
|
44
|
-
// whether a value is walked as a list at all, so one answering `false` makes an index scan report
|
|
45
|
-
// nothing and every rule keyed on what that scan found silently applies to nothing.
|
|
46
12
|
var _isArray = Array.isArray;
|
|
47
13
|
|
|
48
|
-
// The Buffer constructors, snapshotted for the same reason. `Buffer.from` is a writable property
|
|
49
|
-
// of the `Buffer` global and it is how this toolkit turns a backing store into something it can
|
|
50
|
-
// read or clear; one returning a buffer over DIFFERENT memory hands every later step a decoy, so a
|
|
51
|
-
// wipe zeroes the decoy while the plaintext it was aimed at stays readable.
|
|
52
14
|
var _bufferFrom = Buffer.from;
|
|
53
15
|
var _bufferAlloc = Buffer.alloc;
|
|
54
16
|
var _bufferConcat = Buffer.concat;
|
|
55
17
|
var _bufferIsBuffer = Buffer.isBuffer;
|
|
56
18
|
var _bufferByteLength = Buffer.byteLength;
|
|
57
19
|
var _bufferCompare = Buffer.compare;
|
|
58
|
-
// `Buffer.prototype.equals` is the byte-identity test a binding decides on: an OCSP CertID says the
|
|
59
|
-
// response is about this issuer, a responder ID says this key signed it. Dispatched live, one
|
|
60
|
-
// answering true makes a response about a DIFFERENT certificate match the one being asked about.
|
|
61
20
|
var _bufferEquals = uncurry(Buffer.prototype.equals);
|
|
62
|
-
// Buffer#toString, uncurried at load. Used to build dedup keys (a hex string) from bytes the toolkit
|
|
63
|
-
// owns; dispatched live, a replaced toString could make two distinct values key alike or one value key
|
|
64
|
-
// differently on two reads, so a dedup over untrusted-adjacent bytes would merge or split wrongly.
|
|
65
21
|
var _bufferToString = uncurry(Buffer.prototype.toString);
|
|
66
22
|
|
|
67
|
-
// The rest of what a guard reads from the runtime while it is deciding something. These are
|
|
68
|
-
// grouped here rather than captured file by file so the set is enumerable in one place and a guard
|
|
69
|
-
// added later inherits it: a reader asking "what can a caller still reach" has one list to read.
|
|
70
|
-
//
|
|
71
|
-
// The reflective operations are the load-bearing ones. `getOwnPropertyDescriptor` is how the
|
|
72
|
-
// identifier guard learns whether a field is an accessor, `getPrototypeOf` and `ownKeys` are how it
|
|
73
|
-
// walks a chain honestly, and `isView` is how the byte guard recognizes the shape whose backing
|
|
74
|
-
// store it must refuse when shared. A replacement for any of them answers the question the guard
|
|
75
|
-
// asked on the caller's behalf.
|
|
76
23
|
var _isView = ArrayBuffer.isView;
|
|
77
24
|
var _isInteger = Number.isInteger;
|
|
78
25
|
var _isSafeInteger = Number.isSafeInteger;
|
|
@@ -93,24 +40,11 @@ var _mathFloor = Math.floor;
|
|
|
93
40
|
var _mathCeil = Math.ceil;
|
|
94
41
|
var _mathMin = Math.min;
|
|
95
42
|
var _mathMax = Math.max;
|
|
96
|
-
// A numeric parse a bound is then compared against: one answering a larger value widens the bound
|
|
97
|
-
// the comparison was written to enforce.
|
|
98
43
|
var _parseInt = parseInt;
|
|
99
44
|
var _promiseResolve = Promise.resolve;
|
|
100
45
|
var _promiseReject = Promise.reject;
|
|
101
|
-
// The well-known async-iteration symbol, captured at load. `for await` uses this symbol at the
|
|
102
|
-
// language level regardless of the global `Symbol` object, so a classifier that reads
|
|
103
|
-
// `Symbol.asyncIterator` live would disagree with the loop the moment a co-resident replaced the
|
|
104
|
-
// writable `Symbol` global: a real async iterable would be looked up under the wrong key, judged not
|
|
105
|
-
// iterable, and refused where the engine would have consumed it. Reading the captured symbol keeps
|
|
106
|
-
// the door's answer and the loop's behavior the same.
|
|
107
46
|
var _asyncIterator = Symbol.asyncIterator;
|
|
108
47
|
|
|
109
|
-
// The array operations, uncurried at load. These run on arrays the TOOLKIT owns -- an `ownKeys`
|
|
110
|
-
// result, a local accumulator -- so the receiver is never a caller's object; what is caller-
|
|
111
|
-
// reachable is `Array.prototype` itself. A `forEach` replaced with a no-op makes a scan over
|
|
112
|
-
// perfectly real keys report nothing, and a check keyed on what that scan found then passes
|
|
113
|
-
// vacuously, which is the same fail-open shape as an index test that answers `false`.
|
|
114
48
|
var _arrForEach = uncurry(Array.prototype.forEach);
|
|
115
49
|
var _arrMap = uncurry(Array.prototype.map);
|
|
116
50
|
var _arrFilter = uncurry(Array.prototype.filter);
|
|
@@ -123,10 +57,6 @@ var _arrSlice = uncurry(Array.prototype.slice);
|
|
|
123
57
|
var _arrJoin = uncurry(Array.prototype.join);
|
|
124
58
|
var _arrPush = uncurry(Array.prototype.push);
|
|
125
59
|
|
|
126
|
-
// The string and byte-view operations a decision is then made on. A `toUpperCase` or `toLowerCase`
|
|
127
|
-
// replaced after load changes which registry row an algorithm name resolves to; a `subarray`
|
|
128
|
-
// returning a different window hands the next step bytes from somewhere else in the same buffer;
|
|
129
|
-
// and a radix conversion is how a key's own numbers are read back before they are compared.
|
|
130
60
|
var _strToUpperCase = uncurry(String.prototype.toUpperCase);
|
|
131
61
|
var _strToLowerCase = uncurry(String.prototype.toLowerCase);
|
|
132
62
|
var _strIndexOf = uncurry(String.prototype.indexOf);
|
|
@@ -135,11 +65,6 @@ var _abSlice = uncurry(ArrayBuffer.prototype.slice);
|
|
|
135
65
|
var _numToString = uncurry(Number.prototype.toString);
|
|
136
66
|
var _bigIntToString = uncurry(BigInt.prototype.toString);
|
|
137
67
|
|
|
138
|
-
// The collection operations, uncurried. A guard's cycle-safe chain walk is a `Set` it owns, and
|
|
139
|
-
// `has` is what stops it: one answering `true` ends the walk at the first prototype, so a scan that
|
|
140
|
-
// should have found an accessor two levels up reports nothing and the rule keyed on it passes. The
|
|
141
|
-
// registry lookups are the same shape from the other side -- a `get` that answers for a key never
|
|
142
|
-
// stored hands a guard a member list for an object it has never seen.
|
|
143
68
|
var _setAdd = uncurry(Set.prototype.add);
|
|
144
69
|
var _setHas = uncurry(Set.prototype.has);
|
|
145
70
|
var _mapGet = uncurry(Map.prototype.get);
|
|
@@ -149,32 +74,17 @@ var _weakGet = uncurry(WeakMap.prototype.get);
|
|
|
149
74
|
var _weakSet = uncurry(WeakMap.prototype.set);
|
|
150
75
|
var _weakHas = uncurry(WeakMap.prototype.has);
|
|
151
76
|
var _taSet = uncurry(Uint8Array.prototype.set);
|
|
152
|
-
// Own-membership, which is how this toolkit asks whether a key is really in a table rather than
|
|
153
|
-
// inherited from a prototype somebody extended. Spelled `Object.prototype.hasOwnProperty.call(t, k)`
|
|
154
|
-
// it reads two replaceable properties to answer one question, and either of them answering yes puts
|
|
155
|
-
// a name into an allowlist that never contained it.
|
|
156
77
|
var _hasOwn = uncurry(Object.prototype.hasOwnProperty);
|
|
157
|
-
// The conversions, which are globals and so ordinary writable properties of globalThis. They read
|
|
158
|
-
// like language rather than like code, which is why they were the last of these to be noticed: an
|
|
159
|
-
// index test is `String(Number(k)) === k`, a narrow is `Number(v)`, and a header value is
|
|
160
|
-
// `String(value)` before it is scanned for injection. A replacement decides all three.
|
|
161
78
|
var _String = String;
|
|
162
79
|
var _Number = Number;
|
|
163
80
|
var _Boolean = Boolean;
|
|
164
81
|
var _BigInt = BigInt;
|
|
165
82
|
var _Date = Date;
|
|
166
83
|
var _isFinite = globalThis.isFinite;
|
|
167
|
-
// The byte-view constructors, for the same reason: a private copy is only private if the store and
|
|
168
|
-
// the view over it are the ones this code asked for. A replaced constructor hands back a view over
|
|
169
|
-
// storage of its own choosing, while the cleanup still tracks the store that was allocated.
|
|
170
84
|
var _ArrayBuffer = ArrayBuffer;
|
|
171
85
|
var _Uint8Array = Uint8Array;
|
|
172
86
|
var _DataView = DataView;
|
|
173
|
-
// Boxing a primitive, which decides what a reflection scan then sees.
|
|
174
87
|
var _ObjectFn = Object;
|
|
175
|
-
// The prototype OBJECTS, used as identity sentinels: "is this a plain object", "is this a Buffer",
|
|
176
|
-
// "has the chain walk reached the top". Each is reached as a property of a replaceable global, so
|
|
177
|
-
// after a replacement the sentinel is a different object and every comparison against it is false.
|
|
178
88
|
var _ObjectProto = Object.prototype;
|
|
179
89
|
var _BufferProto = Buffer.prototype;
|
|
180
90
|
var _ArrayProto = Array.prototype;
|
|
@@ -182,15 +92,6 @@ var _Set = Set;
|
|
|
182
92
|
var _Map = Map;
|
|
183
93
|
var _WeakMap = WeakMap;
|
|
184
94
|
|
|
185
|
-
// types -- the slot predicates, snapshotted at load.
|
|
186
|
-
//
|
|
187
|
-
// `util.types` is an ordinary object on an ordinary module export, so `util.types.isDate = () =>
|
|
188
|
-
// true` reaches every guard that asks it at call time. These predicates are how this toolkit
|
|
189
|
-
// answers "what IS this value", in preference to a prototype test a caller can satisfy, so a
|
|
190
|
-
// caller who gets to answer them instead has replaced the one question a lookalike cannot lie
|
|
191
|
-
// about. Every own function property is carried across rather than a written-out list, because a
|
|
192
|
-
// list is a thing to get wrong and a predicate added by a later runtime would silently be missing
|
|
193
|
-
// from it.
|
|
194
95
|
var _types = Object.create(null);
|
|
195
96
|
var _typeNames = Object.getOwnPropertyNames(_utilTypes);
|
|
196
97
|
for (var _i = 0; _i < _typeNames.length; _i++) {
|
|
@@ -200,15 +101,6 @@ for (var _i = 0; _i < _typeNames.length; _i++) {
|
|
|
200
101
|
}
|
|
201
102
|
Object.freeze(_types);
|
|
202
103
|
|
|
203
|
-
// uncurry(fn) -> function (receiver, ...args) { return fn.call(receiver, ...args); }
|
|
204
|
-
// fn : the intrinsic captured from a prototype, or an intrinsic getter function.
|
|
205
|
-
//
|
|
206
|
-
// The returned function is private to whichever module called `uncurry`, so no property of it is
|
|
207
|
-
// reachable from outside.
|
|
208
|
-
//
|
|
209
|
-
// A `.call` on a captured intrinsic is the shape this replaces. It reads as safe while being as
|
|
210
|
-
// reachable as the un-captured method was, so it is flagged anywhere in lib/, including a guard
|
|
211
|
-
// not yet written. The safe spelling is also the tripwire for the next one.
|
|
212
104
|
// @enforced-by guard-shape-reinlined
|
|
213
105
|
// @guard-shape \b_[A-Za-z][A-Za-z0-9_$]*\.(?:call|apply)\s*\(
|
|
214
106
|
function uncurry(fn) {
|
|
@@ -218,21 +110,7 @@ function uncurry(fn) {
|
|
|
218
110
|
return _reflectApply(_bind, _call, [fn]);
|
|
219
111
|
}
|
|
220
112
|
|
|
221
|
-
// getter(proto, name, who) -> the prototype's own accessor, uncurried.
|
|
222
|
-
// proto : the intrinsic prototype the accessor lives on.
|
|
223
|
-
// name : the accessor's property name.
|
|
224
|
-
// who : how the prototype is named in the refusal, for a runtime that has no such accessor.
|
|
225
|
-
//
|
|
226
|
-
// A view's size, offset and backing store are accessors on a prototype, which means they are
|
|
227
|
-
// replaceable, which means every rule keyed on one is answerable by whoever replaced it. Taking the
|
|
228
|
-
// descriptor's `get` at load and uncurrying it reads the value's own slot and consults nothing.
|
|
229
|
-
// A runtime without the accessor is refused rather than fallen back from: a fallback here would be
|
|
230
|
-
// the value's own `length`, which is the property this exists to stop reading.
|
|
231
113
|
// @enforced-by behavioral -- reading a descriptor's `get` is not distinguishable from testing one
|
|
232
|
-
// for presence (`!!d.get`, which four guards do legitimately), so a lexical detector would
|
|
233
|
-
// false-fire on every accessor-shape check in the tree; the vectors that replace an accessor and
|
|
234
|
-
// drive the composing guard are the guard. The `.call` half of the shape is covered by uncurry's
|
|
235
|
-
// guard-shape-reinlined detector.
|
|
236
114
|
function getter(proto, name, who) {
|
|
237
115
|
var d = _getOwnPropertyDescriptor(proto, name);
|
|
238
116
|
if (!d || typeof d.get !== "function") {
|
|
@@ -245,24 +123,7 @@ function getter(proto, name, who) {
|
|
|
245
123
|
var _taByteLength = getter(_getPrototypeOf(Uint8Array.prototype), "byteLength", "%TypedArray%.prototype");
|
|
246
124
|
var _dvByteLength = getter(DataView.prototype, "byteLength", "DataView.prototype");
|
|
247
125
|
|
|
248
|
-
// sizeOf(value) -> how large the value is: a string's character count, a view's byte count.
|
|
249
|
-
//
|
|
250
|
-
// The size of an input decides a cap, a bound, an emptiness gate and a loop end all over this
|
|
251
|
-
// toolkit, and `value.length` asks the prototype for it. On a view that property is a replaceable
|
|
252
|
-
// accessor: one reporting a small number for a large buffer disables every size cap at once, and
|
|
253
|
-
// one reporting a positive number for an empty buffer passes an empty secret, an empty DER element
|
|
254
|
-
// and an empty name through the gates that exist to refuse them. So a view is measured from its
|
|
255
|
-
// slot, and a DataView carries its own accessor rather than the typed-array one.
|
|
256
|
-
//
|
|
257
|
-
// A primitive string's `length` is a data property the language maintains and no code can redefine,
|
|
258
|
-
// so the string arm reads it directly. The two arms are one function because a size comparison
|
|
259
|
-
// should have one spelling: a second way to measure is a second thing to get wrong, and the arm
|
|
260
|
-
// that gets skipped is the one that was replaceable. Anything that is neither is refused rather
|
|
261
|
-
// than measured, since its `length` would be whatever its author wrote.
|
|
262
126
|
// @enforced-by behavioral -- `x.length` on a byte view is the same three tokens as on a string or
|
|
263
|
-
// an array, where the read is safe and ubiquitous, and the receiver's kind is not knowable
|
|
264
|
-
// statically in this codebase's style; a detector would flag every array bound in the tree. The
|
|
265
|
-
// over-cap and control-byte vectors under a replaced accessor are the guard.
|
|
266
127
|
function sizeOf(value) {
|
|
267
128
|
if (typeof value === "string") return value.length;
|
|
268
129
|
if (_types.isDataView(value)) return _dvByteLength(value);
|
|
@@ -271,11 +132,6 @@ function sizeOf(value) {
|
|
|
271
132
|
(value === null ? "null" : typeof value));
|
|
272
133
|
}
|
|
273
134
|
|
|
274
|
-
// Frozen, and that is what makes the capture worth taking. A consumer binds these at load, but it
|
|
275
|
-
// also reads several of them as `intrinsic.<name>(...)` at the call itself, and the module registry
|
|
276
|
-
// hands every caller this same object: assigning one property would redirect that call in every
|
|
277
|
-
// module at once, which is the substitution the captures exist to refuse. Freezing costs nothing
|
|
278
|
-
// here because nothing writes to it after load.
|
|
279
135
|
module.exports = Object.freeze({
|
|
280
136
|
uncurry: uncurry,
|
|
281
137
|
getter: getter,
|
|
@@ -333,12 +189,7 @@ module.exports = Object.freeze({
|
|
|
333
189
|
arraySlice: _arrSlice,
|
|
334
190
|
join: _arrJoin,
|
|
335
191
|
hasOwn: _hasOwn,
|
|
336
|
-
// Invocation itself. `fn.apply(...)` reads `apply` off Function.prototype, so a replacement
|
|
337
|
-
// decides whether a verb's body runs at all and what it appears to return; `Reflect.apply` is
|
|
338
|
-
// invoked directly and consults no property of the function.
|
|
339
192
|
apply: _reflectApply,
|
|
340
|
-
// And the cleanup half of a promise chain: `.finally` is where a copied secret is released, so a
|
|
341
|
-
// replacement that drops its callback leaves the plaintext copy alive for the process's lifetime.
|
|
342
193
|
promiseFinally: uncurry(Promise.prototype["finally"]),
|
|
343
194
|
String: _String,
|
|
344
195
|
Number: _Number,
|
package/lib/guard-json.js
CHANGED
|
@@ -1,72 +1,27 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) blamejs contributors
|
|
3
3
|
"use strict";
|
|
4
|
-
//
|
|
5
|
-
// @internal -- no operator-facing namespace. The documented surface is the
|
|
6
|
-
// consumers whose JSON integrity composes this guard (pki.jose message parsing,
|
|
7
|
-
// pki.acme resource objects, pki.webcrypto JWK unwrap).
|
|
8
|
-
//
|
|
9
|
-
// guard-json -- strict, bounded parse of an untrusted JSON document. JSON.parse
|
|
10
|
-
// silently takes the last value of a duplicate member, so a signed or wrapped
|
|
11
|
-
// object carrying two members of the same name resolves differently for a
|
|
12
|
-
// verifier than for a consumer. That is the JSON smuggling / parser-differential
|
|
13
|
-
// class (CWE-20 / CWE-436). It also caps neither size nor nesting (CWE-770 /
|
|
14
|
-
// CWE-400), and over a Buffer substitutes U+FFFD for invalid UTF-8 instead of failing.
|
|
15
|
-
//
|
|
16
|
-
// This is a single hand-written recursive-descent reader that composes
|
|
17
|
-
// guard.text.decode (the byte cap runs before the strict/fatal UTF-8 decode, so
|
|
18
|
-
// an oversized document is rejected before it is materialized), then rejects a
|
|
19
|
-
// duplicate member at every nesting depth, caps nesting, assigns each member as
|
|
20
|
-
// an own data property (a "__proto__" key becomes a normal member: it cannot
|
|
21
|
-
// mutate the prototype nor, being a non-own assignment for a primitive, silently
|
|
22
|
-
// defeat the duplicate-member gate), and enforces the RFC 8259 number/string
|
|
23
|
-
// grammar (no leading zero, a fraction/exponent needs a digit, no bare "-").
|
|
24
|
-
//
|
|
4
|
+
// @internal
|
|
25
5
|
var text = require("./guard-text");
|
|
26
|
-
// Taken at load. `defineProperty` is how a decoded member lands on the result without consulting a
|
|
27
|
-
// setter, and `fromCharCode` is how an escape becomes the character it names; a replacement for
|
|
28
|
-
// either decides what this parser produces. See guard-intrinsic for the whole captured set.
|
|
29
6
|
var _defineProperty = require("./guard-intrinsic").defineProperty;
|
|
30
7
|
var _freeze = require("./guard-intrinsic").freeze;
|
|
31
8
|
var _fromCharCode = require("./guard-intrinsic").fromCharCode;
|
|
32
|
-
// The character-code read the whole scanner is built on: whitespace, escapes and the control-byte
|
|
33
|
-
// reject all consult it, so one that lies decides what this parser sees in the input.
|
|
34
9
|
var _charCodeAt = require("./guard-intrinsic").uncurry(String.prototype.charCodeAt);
|
|
35
|
-
// The scanner has already found where a number literal starts and ends; this is the step that cuts
|
|
36
|
-
// it out. A replacement hands `Number` a different span than the one the parser validated, so the
|
|
37
|
-
// value the document is understood to carry is not the value its bytes spell.
|
|
38
10
|
var _strSlice = require("./guard-intrinsic").uncurry(String.prototype.slice);
|
|
39
|
-
// The duplicate-member gate below asks whether a key is already present. Spelled
|
|
40
|
-
// `Object.prototype.hasOwnProperty.call(...)` it reads two replaceable properties to answer that,
|
|
41
|
-
// and either of them answering wrongly lets a document carry the same member twice.
|
|
42
11
|
var _hasOwn = require("./guard-intrinsic").hasOwn;
|
|
43
|
-
// The conversion that turns a validated number literal into the value the document is understood to
|
|
44
|
-
// carry. A replacement returns something else for text this parser has already checked.
|
|
45
12
|
var _Number = require("./guard-intrinsic").Number;
|
|
46
|
-
// The gate that refuses a numeric token that overflowed to Infinity. A replacement answering true
|
|
47
|
-
// admits it, and the document is understood to carry a value its bytes cannot spell.
|
|
48
13
|
var _isFinite = require("./guard-intrinsic").isFinite;
|
|
49
14
|
var _stringify = require("./guard-intrinsic").stringify;
|
|
50
|
-
// Appended by index rather than through `push`, so the growth reads no prototype method at all.
|
|
51
15
|
function _append(arr, v) { _defineProperty(arr, arr.length, { value: v, writable: true, enumerable: true, configurable: true }); }
|
|
52
16
|
var limits = require("./guard-limits");
|
|
53
17
|
|
|
54
|
-
// One hex digit's value, or -1. Written out because the three ranges ARE the rule.
|
|
55
18
|
function _hexVal(c) {
|
|
56
|
-
if (c >= 0x30 && c <= 0x39) return c - 0x30;
|
|
57
|
-
if (c >= 0x61 && c <= 0x66) return c - 0x61 + 10;
|
|
58
|
-
if (c >= 0x41 && c <= 0x46) return c - 0x41 + 10;
|
|
19
|
+
if (c >= 0x30 && c <= 0x39) return c - 0x30;
|
|
20
|
+
if (c >= 0x61 && c <= 0x66) return c - 0x61 + 10;
|
|
21
|
+
if (c >= 0x41 && c <= 0x46) return c - 0x41 + 10;
|
|
59
22
|
return -1;
|
|
60
23
|
}
|
|
61
24
|
|
|
62
|
-
// parse(input, ErrorClass, spec) -> value. `input` is a Buffer or a string.
|
|
63
|
-
// spec = { maxBytes, maxDepth, badJson, tooDeep, duplicateMember, tooLarge,
|
|
64
|
-
// badInput, label }, the caller's caps and frozen domain/reason codes.
|
|
65
|
-
// Both caps are required authoring inputs: an omitted, NaN or fractional cap
|
|
66
|
-
// would silently disable the bound it configures (a depth-uncapped recursive
|
|
67
|
-
// descent escapes as a raw stack-overflow RangeError), so they are validated
|
|
68
|
-
// through the shared cap guards at entry, maxDepth additionally against the
|
|
69
|
-
// stack-safe recursion ceiling, so no caller cap can exceed frame safety.
|
|
70
25
|
// @enforced-by json-parse-not-via-guard
|
|
71
26
|
function parse(input, ErrorClass, spec) {
|
|
72
27
|
function E(code, message, cause) { return new ErrorClass(code, message, cause); }
|
|
@@ -75,8 +30,6 @@ function parse(input, ErrorClass, spec) {
|
|
|
75
30
|
}
|
|
76
31
|
var maxBytes = limits.cap(spec.maxBytes, "guard.json.parse spec.maxBytes", undefined);
|
|
77
32
|
var maxDepth = limits.depthCap(spec.maxDepth, "guard.json.parse spec.maxDepth", undefined);
|
|
78
|
-
// Byte cap before the fatal UTF-8 decode (an oversized/ill-encoded document is
|
|
79
|
-
// rejected before it is turned into a string).
|
|
80
33
|
var str = text.decode(input, maxBytes, ErrorClass, {
|
|
81
34
|
charset: "utf-8", fatal: true, tooLarge: spec.tooLarge, badDecode: spec.badJson, badInput: spec.badInput, label: spec.label,
|
|
82
35
|
});
|
|
@@ -92,8 +45,6 @@ function parse(input, ErrorClass, spec) {
|
|
|
92
45
|
if (c === "[") return array(depth);
|
|
93
46
|
if (c === "\"") return string();
|
|
94
47
|
if (c === "-" || (c >= "0" && c <= "9")) return number();
|
|
95
|
-
// Through the captured slice, not `substr`: these three comparisons ARE the literal grammar, so
|
|
96
|
-
// one returning something else accepts a token the document does not spell.
|
|
97
48
|
if (_strSlice(str, i, i + 4) === "true") { i += 4; return true; }
|
|
98
49
|
if (_strSlice(str, i, i + 5) === "false") { i += 5; return false; }
|
|
99
50
|
if (_strSlice(str, i, i + 4) === "null") { i += 4; return null; }
|
|
@@ -101,7 +52,7 @@ function parse(input, ErrorClass, spec) {
|
|
|
101
52
|
return undefined;
|
|
102
53
|
}
|
|
103
54
|
function object(depth) {
|
|
104
|
-
i++;
|
|
55
|
+
i++;
|
|
105
56
|
var out = {};
|
|
106
57
|
ws();
|
|
107
58
|
if (str[i] === "}") { i++; return out; }
|
|
@@ -113,8 +64,6 @@ function parse(input, ErrorClass, spec) {
|
|
|
113
64
|
ws();
|
|
114
65
|
if (str[i] !== ":") fail("expected ':'");
|
|
115
66
|
i++;
|
|
116
|
-
// Own data property (not out[key]=...): a "__proto__" key becomes a normal
|
|
117
|
-
// member, never a prototype mutation nor a silent duplicate-gate bypass.
|
|
118
67
|
_defineProperty(out, key, { value: value(depth + 1), writable: true, enumerable: true, configurable: true });
|
|
119
68
|
ws();
|
|
120
69
|
if (str[i] === ",") { i++; continue; }
|
|
@@ -123,7 +72,7 @@ function parse(input, ErrorClass, spec) {
|
|
|
123
72
|
}
|
|
124
73
|
}
|
|
125
74
|
function array(depth) {
|
|
126
|
-
i++;
|
|
75
|
+
i++;
|
|
127
76
|
var out = [];
|
|
128
77
|
ws();
|
|
129
78
|
if (str[i] === "]") { i++; return out; }
|
|
@@ -136,7 +85,7 @@ function parse(input, ErrorClass, spec) {
|
|
|
136
85
|
}
|
|
137
86
|
}
|
|
138
87
|
function string() {
|
|
139
|
-
i++;
|
|
88
|
+
i++;
|
|
140
89
|
var s = "";
|
|
141
90
|
for (;;) {
|
|
142
91
|
if (i >= n) fail("unterminated string");
|
|
@@ -154,9 +103,6 @@ function parse(input, ErrorClass, spec) {
|
|
|
154
103
|
else if (e === "r") s += "\r";
|
|
155
104
|
else if (e === "t") s += "\t";
|
|
156
105
|
else if (e === "u") {
|
|
157
|
-
// Four hex digits, read as digits instead of matched as a pattern: the
|
|
158
|
-
// scanner is already walking this string one character at a time, and a
|
|
159
|
-
// parser handed hostile input should not hand any of it to a second engine.
|
|
160
106
|
var cp = 0;
|
|
161
107
|
if (i + 4 > n) fail("bad \\u escape");
|
|
162
108
|
for (var h = 0; h < 4; h++) {
|
|
@@ -172,13 +118,6 @@ function parse(input, ErrorClass, spec) {
|
|
|
172
118
|
} else s += c;
|
|
173
119
|
}
|
|
174
120
|
}
|
|
175
|
-
// RFC 8259 sec. 6, enforced by the walk itself and not by re-matching the token
|
|
176
|
-
// afterwards. The scan already knows where each part starts and ends, so the
|
|
177
|
-
// grammar's three rules (an integer part that is "0" or has no leading zero, a
|
|
178
|
-
// fraction with at least one digit, an exponent with at least one digit) are
|
|
179
|
-
// checked as it goes. Re-matching what the scanner just read meant maintaining
|
|
180
|
-
// the same grammar twice, in two notations, and the pattern was the copy whose
|
|
181
|
-
// cost on a rejecting token could not be bounded from outside.
|
|
182
121
|
function number() {
|
|
183
122
|
var start = i;
|
|
184
123
|
if (str[i] === "-") i++;
|
|
@@ -186,19 +125,19 @@ function parse(input, ErrorClass, spec) {
|
|
|
186
125
|
while (i < n && str[i] >= "0" && str[i] <= "9") i++;
|
|
187
126
|
var intLen = i - intStart;
|
|
188
127
|
if (intLen === 0) fail("malformed number");
|
|
189
|
-
if (intLen > 1 && str[intStart] === "0") fail("malformed number");
|
|
128
|
+
if (intLen > 1 && str[intStart] === "0") fail("malformed number");
|
|
190
129
|
if (str[i] === ".") {
|
|
191
130
|
i++;
|
|
192
131
|
var fracStart = i;
|
|
193
132
|
while (i < n && str[i] >= "0" && str[i] <= "9") i++;
|
|
194
|
-
if (i === fracStart) fail("malformed number");
|
|
133
|
+
if (i === fracStart) fail("malformed number");
|
|
195
134
|
}
|
|
196
135
|
if (str[i] === "e" || str[i] === "E") {
|
|
197
136
|
i++;
|
|
198
137
|
if (str[i] === "+" || str[i] === "-") i++;
|
|
199
138
|
var expStart = i;
|
|
200
139
|
while (i < n && str[i] >= "0" && str[i] <= "9") i++;
|
|
201
|
-
if (i === expStart) fail("malformed number");
|
|
140
|
+
if (i === expStart) fail("malformed number");
|
|
202
141
|
}
|
|
203
142
|
var v = _Number(_strSlice(str, start, i));
|
|
204
143
|
if (!_isFinite(v)) fail("bad number");
|
|
@@ -210,6 +149,4 @@ function parse(input, ErrorClass, spec) {
|
|
|
210
149
|
return result;
|
|
211
150
|
}
|
|
212
151
|
|
|
213
|
-
// Frozen for the reason the family header gives: a boundary reads its guard off this object at the
|
|
214
|
-
// call, so a writable export would let a caller replace the check rather than pass it.
|
|
215
152
|
module.exports = _freeze({ parse: parse });
|
package/lib/guard-limits.js
CHANGED
|
@@ -1,63 +1,18 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) blamejs contributors
|
|
3
3
|
"use strict";
|
|
4
|
-
//
|
|
5
|
-
// @internal -- no operator-facing namespace. The documented surface is the
|
|
6
|
-
// decoders whose option validation composes these guards (pki.asn1.decode,
|
|
7
|
-
// pki.cbor.decode).
|
|
8
|
-
//
|
|
9
|
-
// guard-limits -- fail-closed validation of operator-supplied decode limits at
|
|
10
|
-
// config time (the tier that throws on a bad argument so the operator catches
|
|
11
|
-
// the typo at boot). Enforced choke point: a codebase-patterns detector requires
|
|
12
|
-
// the stack-safe recursion ceiling to live only here, so a new decoder cannot be
|
|
13
|
-
// configured past it.
|
|
14
|
-
//
|
|
15
|
-
// Defends the parser-DoS / resource-exhaustion class (CWE-834 excessive
|
|
16
|
-
// recursion, CWE-770 allocation without limits; MITRE T1499.001; D3FEND
|
|
17
|
-
// Recursion-Bounding + Input-Size-Restriction). A recursive-descent decoder
|
|
18
|
-
// bounded only by a caller-tunable maxDepth overflows the native call stack (a
|
|
19
|
-
// raw RangeError, not a typed verdict) once the cap is raised past the frame
|
|
20
|
-
// limit; depthCap refuses a maxDepth above the stack-safe ceiling. A bad limit
|
|
21
|
-
// is an authoring bug, so this tier throws a TypeError (not a PkiError). NIST
|
|
22
|
-
// 800-53 SI-10 / SC-5 do not require these bounds (framework lag). The control
|
|
23
|
-
// that actually holds is the bound at the parser.
|
|
4
|
+
// @internal
|
|
24
5
|
|
|
25
6
|
var constants = require("./constants");
|
|
26
|
-
// The integer test, taken at load. Every bound below is only a bound while this answers honestly:
|
|
27
|
-
// one returning true admits a NaN or fractional cap, which makes the comparison it guards always
|
|
28
|
-
// false. See guard-intrinsic for the whole captured set.
|
|
29
7
|
var _isInteger = require("./guard-intrinsic").isInteger;
|
|
30
8
|
var _freeze = require("./guard-intrinsic").freeze;
|
|
31
|
-
// And the size measurement, for the same reason one step further in: a cap compares against a
|
|
32
|
-
// length, and on a byte view `length` is a replaceable accessor. One reporting a small number for a
|
|
33
|
-
// large buffer leaves every byteCap below always-false, which is the size defense silently dead.
|
|
34
9
|
var _sizeOf = require("./guard-intrinsic").sizeOf;
|
|
35
10
|
|
|
36
|
-
// cap(value, key, dflt, opts) -> a validated bounded integer, or dflt when value
|
|
37
|
-
// is undefined. A non-integer / non-finite / negative value fails closed
|
|
38
|
-
// (Number.isInteger already rejects non-numbers, NaN, and Infinity).
|
|
39
|
-
//
|
|
40
|
-
// With no opts it is the config-time codec default: a bare TypeError with the
|
|
41
|
-
// "decode:" prefix and a >= 0 floor (the asn1-der / cbor-det callers are
|
|
42
|
-
// untouched). opts lets a caller in another currency reuse the same integer
|
|
43
|
-
// floor with its own typed verdict and bounds, so a fractional/negative/NaN
|
|
44
|
-
// bound cannot be spelled a fifth way with a dropped Number.isInteger:
|
|
45
|
-
// E - a (code, message) -> Error factory; when given, an out-of-range
|
|
46
|
-
// value throws E(code, ...) instead of the bare TypeError.
|
|
47
|
-
// code - the domain/reason code passed to E.
|
|
48
|
-
// label - names the argument in the message (defaults to key).
|
|
49
|
-
// min - inclusive lower bound (default 0).
|
|
50
|
-
// max - inclusive upper bound (optional).
|
|
51
11
|
// @enforced-by behavioral -- a config-time cap validator has no rename-proof code
|
|
52
|
-
// shape; the decode-rejects-a-bad-cap RED vectors (asn1/cbor/path) are the guard.
|
|
53
12
|
function cap(value, key, dflt, opts) {
|
|
54
13
|
if (value === undefined) return dflt;
|
|
55
14
|
opts = opts || {};
|
|
56
15
|
var min = opts.min === undefined ? 0 : opts.min;
|
|
57
|
-
// The bounds themselves are authoring inputs: a NaN / fractional min or max
|
|
58
|
-
// compares false against every value, silently disabling the check (a NaN min
|
|
59
|
-
// even REPLACES the default >= 0 floor). Always a config-time TypeError --
|
|
60
|
-
// the bound wiring is broken regardless of the value currency opts.E selects.
|
|
61
16
|
if (!_isInteger(min) || (opts.max !== undefined && !_isInteger(opts.max))) {
|
|
62
17
|
throw new TypeError("guard.limits.cap: the min/max bounds for " + key + " must be integers");
|
|
63
18
|
}
|
|
@@ -70,9 +25,6 @@ function cap(value, key, dflt, opts) {
|
|
|
70
25
|
return value;
|
|
71
26
|
}
|
|
72
27
|
|
|
73
|
-
// depthCap(value, key, dflt) -> a validated recursion-depth cap: cap() plus the
|
|
74
|
-
// stack-safe ceiling, so a raised maxDepth cannot drive recursive descent into a
|
|
75
|
-
// raw RangeError past the native frame limit.
|
|
76
28
|
// @enforced-by guard-shape-reinlined
|
|
77
29
|
// @guard-scope file
|
|
78
30
|
// @guard-shape \bopts\.maxDepth\b
|
|
@@ -86,20 +38,8 @@ function depthCap(value, key, dflt) {
|
|
|
86
38
|
return n;
|
|
87
39
|
}
|
|
88
40
|
|
|
89
|
-
// counter(max, E, code, label) -> { tick }. A parse-time item counter: the
|
|
90
|
-
// recursive decoder calls tick() once per decoded element so a small input
|
|
91
|
-
// cannot fan out into a massive eager node/element tree (CWE-770 / CWE-400 memory
|
|
92
|
-
// amplification -- the class pki.cbor closed with CBOR_MAX_ITEMS). Unlike cap
|
|
93
|
-
// (config-time TypeError), this is Tier-2 parse validation: an over-count throws
|
|
94
|
-
// the caller's typed PkiError via the E(code, message) factory. `max` is the
|
|
95
|
-
// caller's already-validated ceiling (an opts.maxItems run through cap()).
|
|
96
41
|
// @enforced-by behavioral -- a monotone counter has no rename-proof code shape
|
|
97
|
-
// distinct from any `n++ > max` loop bound; the memory-fanout RED vectors (a
|
|
98
|
-
// dense TLV run rejects at the cap) driving the composing decoders are the guard.
|
|
99
42
|
function counter(max, E, code, label) {
|
|
100
|
-
// The ceiling is an authoring input: an undefined / NaN / fractional max
|
|
101
|
-
// builds a counter whose `n > max` never fires, leaving a silently dead fanout
|
|
102
|
-
// defense. Reject at construction (config-time TypeError).
|
|
103
43
|
if (!_isInteger(max) || max < 0) {
|
|
104
44
|
throw new TypeError("guard.limits.counter: max must be a non-negative integer");
|
|
105
45
|
}
|
|
@@ -112,22 +52,8 @@ function counter(max, E, code, label) {
|
|
|
112
52
|
};
|
|
113
53
|
}
|
|
114
54
|
|
|
115
|
-
// byteCap(buf, max, E, code, label) -> the same buffer, once proven within `max`
|
|
116
|
-
// bytes. Bounds a caller-supplied buffer before an expensive hash / verify / parse
|
|
117
|
-
// materializes over it (CWE-400 uncontrolled resource consumption / CWE-770
|
|
118
|
-
// allocation without limits -- the class guard.text.decode closes for a decoded
|
|
119
|
-
// string and counter closes for element fanout, here for a raw byte input). Tier-2:
|
|
120
|
-
// an over-size input is hostile / malformed content, so it throws the caller's typed
|
|
121
|
-
// PkiError via the E(code, message) factory. `max` is the caller's ceiling (a
|
|
122
|
-
// C.LIMITS.* constant, or an operator max already run through cap()).
|
|
123
55
|
// @enforced-by behavioral -- a `buf.length > cap` size gate has no rename-proof code
|
|
124
|
-
// shape distinct from an arity / field-width check (children.length > 2,
|
|
125
|
-
// ext.length > 0xffff), so a codebase-patterns detector would false-fire; the
|
|
126
|
-
// over-size RED vectors driving the composing verifiers are the guard.
|
|
127
56
|
function byteCap(buf, max, E, code, label) {
|
|
128
|
-
// The ceiling is an authoring input: an undefined / NaN / fractional / negative
|
|
129
|
-
// max makes `length > max` never fire, and the size defense is then silently
|
|
130
|
-
// dead. Reject at config time (TypeError), regardless of the value currency E selects.
|
|
131
57
|
if (!_isInteger(max) || max < 0) {
|
|
132
58
|
throw new TypeError("guard.limits.byteCap: max must be a non-negative integer");
|
|
133
59
|
}
|
|
@@ -138,6 +64,4 @@ function byteCap(buf, max, E, code, label) {
|
|
|
138
64
|
return buf;
|
|
139
65
|
}
|
|
140
66
|
|
|
141
|
-
// Frozen for the reason the family header gives: a boundary reads its guard off this object at the
|
|
142
|
-
// call, so a writable export would let a caller replace the check rather than pass it.
|
|
143
67
|
module.exports = _freeze({ cap: cap, depthCap: depthCap, counter: counter, byteCap: byteCap });
|