@blamejs/core 0.9.7 → 0.9.9
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 +2 -0
- package/index.js +2 -0
- package/lib/auth/password.js +5 -4
- package/lib/cli.js +9 -3
- package/lib/db-schema.js +4 -1
- package/lib/external-db-migrate.js +4 -1
- package/lib/mail-bimi.js +8 -9
- package/lib/migrations.js +3 -1
- package/lib/public-suffix.js +19 -30
- package/lib/seeders.js +3 -1
- package/lib/vendor/.vendor-data-pubkey +4 -0
- package/lib/vendor/MANIFEST.json +156 -144
- package/lib/vendor/bimi-trust-anchors.data.js +68 -0
- package/lib/vendor/common-passwords-top-10000.data.js +1325 -0
- package/lib/vendor/common-passwords-top-10000.txt +2 -0
- package/lib/vendor/public-suffix-list.dat +6 -0
- package/lib/vendor/public-suffix-list.data.js +5881 -0
- package/lib/vendor/vendor-data-pubkey.js +16 -0
- package/lib/vendor-data.js +363 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// vendor-data-pubkey — SLH-DSA-SHAKE-256f public key inlined as a CommonJS
|
|
2
|
+
// module so lib/vendor-data.js can verify .data.js signatures without
|
|
3
|
+
// any fs.readFileSync call. Packaging-mode-invariant (SEA / pkg / nexe /
|
|
4
|
+
// esbuild / Bun compile / Deno compile / Lambda all preserve require()
|
|
5
|
+
// resolution but not __dirname-relative file lookups).
|
|
6
|
+
//
|
|
7
|
+
// Fingerprint (SHA-256 of the raw SPKI): dd02aaf2f700e1403172f1e57619ba6308642e107853891866ffd8589b4164d1
|
|
8
|
+
//
|
|
9
|
+
// Regenerated by scripts/vendor-data-keygen.js whenever the maintainer
|
|
10
|
+
// vendor-data signing key rotates. The companion PEM at
|
|
11
|
+
// lib/vendor/.vendor-data-pubkey is the operator-readable form; this
|
|
12
|
+
// JS module is the runtime form. Both regenerate together.
|
|
13
|
+
|
|
14
|
+
"use strict";
|
|
15
|
+
|
|
16
|
+
module.exports = "-----BEGIN SLH-DSA-SHAKE-256F PUBLIC KEY-----\nNyFNN00fxmgkHnZwtfy1FU9SodrVbgJRihT5/S605tM7c6YAKIS1mry4y8VCKh2h\nG+oRhGOPLb1ebxNmcQZw+g==\n-----END SLH-DSA-SHAKE-256F PUBLIC KEY-----\n";
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module b.vendorData
|
|
4
|
+
* @nav Supply Chain
|
|
5
|
+
* @title Vendor Data — packaging-mode-invariant + signed + canary-guarded
|
|
6
|
+
* @order 710
|
|
7
|
+
*
|
|
8
|
+
* @intro
|
|
9
|
+
* Loader for vendored data files that ship inside the framework
|
|
10
|
+
* tarball (`lib/vendor/*`). Inline-as-JS means the data survives any
|
|
11
|
+
* packaging mode — SEA, esbuild bundle, `pkg`, `nexe`, Bun compile,
|
|
12
|
+
* AWS Lambda — without `__dirname`-relative `fs.readFileSync` paths
|
|
13
|
+
* collapsing under the bundler. Every load runs four orthogonal
|
|
14
|
+
* integrity checks before returning a byte to the caller:
|
|
15
|
+
*
|
|
16
|
+
* 1. SHA-256 of the embedded payload matches the expected constant
|
|
17
|
+
* 2. SHA3-512 of the embedded payload matches the expected constant
|
|
18
|
+
* 3. SLH-DSA-SHAKE-256f signature over the payload verifies against
|
|
19
|
+
* the maintainer's pinned public key (`lib/vendor/.vendor-data-pubkey`)
|
|
20
|
+
* 4. The known canary entry (where applicable per data file) is
|
|
21
|
+
* present in the parsed payload — defends against content swap
|
|
22
|
+
* even when an attacker forges hashes + signatures
|
|
23
|
+
*
|
|
24
|
+
* Refusal at any step throws `VendorDataError`. `verifyAll()` runs
|
|
25
|
+
* at framework boot so a tampered vendor file is a fail-fast — not
|
|
26
|
+
* a first-request-touches-PSL surprise.
|
|
27
|
+
*
|
|
28
|
+
* Each vendored data file ships as a `<name>.data.js` module that
|
|
29
|
+
* exports `{ payload, metadata, canary }`. The `.data.js` is
|
|
30
|
+
* regenerated by `scripts/vendor-update.sh --refresh-data` whenever
|
|
31
|
+
* the upstream source is refreshed; it is never hand-edited.
|
|
32
|
+
*
|
|
33
|
+
* @card
|
|
34
|
+
* Signed + dual-hashed + canary-guarded loader for vendored data.
|
|
35
|
+
* Survives SEA / pkg / bundler builds because the data is inline,
|
|
36
|
+
* not `fs.readFileSync`-loaded.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
var nodeCrypto = require("crypto");
|
|
40
|
+
var safeEnv = require("./parsers/safe-env");
|
|
41
|
+
var { defineClass } = require("./framework-error");
|
|
42
|
+
var pqcSoftware = require("./pqc-software");
|
|
43
|
+
|
|
44
|
+
// Framework-pinned vendor-data public key. Inlined as a CommonJS
|
|
45
|
+
// module (lib/vendor/vendor-data-pubkey.js) so the loader has zero
|
|
46
|
+
// fs.readFileSync calls and survives any packaging mode that
|
|
47
|
+
// preserves require() resolution (SEA, pkg, nexe, esbuild, Bun /
|
|
48
|
+
// Deno compile, Lambda layers). The companion PEM at
|
|
49
|
+
// lib/vendor/.vendor-data-pubkey is the operator-readable form for
|
|
50
|
+
// external inspection; this JS module is the runtime trust root.
|
|
51
|
+
// Both regenerate together whenever the maintainer signing key
|
|
52
|
+
// rotates (scripts/vendor-data-keygen.js).
|
|
53
|
+
var PUBKEY_PEM = require("./vendor/vendor-data-pubkey");
|
|
54
|
+
|
|
55
|
+
// Static require()s — every modern bundler (esbuild, webpack, ncc,
|
|
56
|
+
// rollup, Bun's bundler, Deno's bundler) traces these at bundle time
|
|
57
|
+
// only when the require() argument is a STRING LITERAL. A dynamic
|
|
58
|
+
// `require(variable)` is opaque to static analysis: bundlers can't
|
|
59
|
+
// determine what files to include, so the .data.js payloads silently
|
|
60
|
+
// fall out of the SEA / pkg / nexe / esbuild blob and the SEA-mode
|
|
61
|
+
// promise of v0.9.8 is defeated at boot. Each require below sits at
|
|
62
|
+
// column 0 with a literal-string argument so static analysis traces
|
|
63
|
+
// them; codebase-patterns enforces this via the testNoDynamicRequires
|
|
64
|
+
// + testNoInlineRequires detectors.
|
|
65
|
+
var _PSL_DATA = require("./vendor/public-suffix-list.data");
|
|
66
|
+
var _COMMON_PW_DATA = require("./vendor/common-passwords-top-10000.data");
|
|
67
|
+
var _BIMI_ANCHORS_DATA = require("./vendor/bimi-trust-anchors.data");
|
|
68
|
+
|
|
69
|
+
var _MODULES = {
|
|
70
|
+
"public-suffix-list": _PSL_DATA,
|
|
71
|
+
"common-passwords-top-10000": _COMMON_PW_DATA,
|
|
72
|
+
"bimi-trust-anchors": _BIMI_ANCHORS_DATA,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
var VendorDataError = defineClass("VendorDataError", { alwaysPermanent: true });
|
|
76
|
+
|
|
77
|
+
// KNOWN_VENDOR_DATA — the canonical list of vendored data names. Each
|
|
78
|
+
// entry carries the canary token the payload must contain after parse
|
|
79
|
+
// (where applicable) and a description for the inventory surface.
|
|
80
|
+
//
|
|
81
|
+
// The `module` string is documentation-only as of v0.9.9 — the runtime
|
|
82
|
+
// uses the `_MODULES` table above (static literal-string requires) so
|
|
83
|
+
// bundlers can statically trace the .data.js dependency. The `module`
|
|
84
|
+
// field stays exported for downstream tooling that inspects
|
|
85
|
+
// `b.vendorData.KNOWN_VENDOR_DATA[name].module` for diagnostics or
|
|
86
|
+
// vendor-refresh tooling. NEVER call `require(entry.module)` — dynamic
|
|
87
|
+
// require(variable) breaks SEA / esbuild / pkg bundling.
|
|
88
|
+
var KNOWN_VENDOR_DATA = Object.freeze({
|
|
89
|
+
"public-suffix-list": {
|
|
90
|
+
module: "./vendor/public-suffix-list.data",
|
|
91
|
+
canary: "_blamejs_canary_v0_9_8_.local",
|
|
92
|
+
// Canary parse check — operator-side `b.publicSuffix.isPublicSuffix(canary)`
|
|
93
|
+
// MUST return true after the PSL parser ingests the data. The check
|
|
94
|
+
// is run by every `get()` via the .data.js's canaryCheck closure.
|
|
95
|
+
description: "Mozilla Public Suffix List (PSL). Used by b.publicSuffix for organizational-domain + public-suffix lookups.",
|
|
96
|
+
},
|
|
97
|
+
"common-passwords-top-10000": {
|
|
98
|
+
module: "./vendor/common-passwords-top-10000.data",
|
|
99
|
+
canary: "_blamejs_canary_password_2026_05_13_blamejs_internal_",
|
|
100
|
+
description: "Top-10000 most common passwords (SecLists). Used by b.auth.password to refuse known-breached credentials.",
|
|
101
|
+
},
|
|
102
|
+
"bimi-trust-anchors": {
|
|
103
|
+
module: "./vendor/bimi-trust-anchors.data",
|
|
104
|
+
canary: null,
|
|
105
|
+
// BIMI trust anchor file is a PEM bundle; injecting an in-payload
|
|
106
|
+
// canary would require minting a real self-signed cert against
|
|
107
|
+
// every refresh which would inflate the vendor pipeline. The
|
|
108
|
+
// dual-hash + SLH-DSA signature layers cover the threat; canary
|
|
109
|
+
// is intentionally skipped for this entry.
|
|
110
|
+
description: "BIMI Group VMC + CMC trust anchors. Used by b.mail.bimi.fetchAndVerifyMark for chain validation.",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Per-name cache so verify-once-on-first-load + boot-time verifyAll
|
|
115
|
+
// don't pay the SLH-DSA-SHAKE-256f verify cost twice. Cached entries
|
|
116
|
+
// are payload Buffers (caller-receivable); signature verification
|
|
117
|
+
// runs at module-load (in `_loadAndVerify`), not at every `get()`.
|
|
118
|
+
var _payloadCache = Object.create(null);
|
|
119
|
+
|
|
120
|
+
function _loadAndVerify(name) {
|
|
121
|
+
if (_payloadCache[name]) return _payloadCache[name];
|
|
122
|
+
|
|
123
|
+
var entry = KNOWN_VENDOR_DATA[name];
|
|
124
|
+
if (!entry) {
|
|
125
|
+
throw new VendorDataError("vendor-data/unknown",
|
|
126
|
+
"vendorData: '" + name + "' not in KNOWN_VENDOR_DATA. " +
|
|
127
|
+
"Registered names: " + Object.keys(KNOWN_VENDOR_DATA).join(", "));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
var mod = _MODULES[name];
|
|
131
|
+
if (!mod) {
|
|
132
|
+
throw new VendorDataError("vendor-data/module-missing",
|
|
133
|
+
"vendorData: '" + name + "' .data.js module not statically " +
|
|
134
|
+
"require'd by lib/vendor-data.js. Add the literal-string require " +
|
|
135
|
+
"to the _MODULES table at the top of the file — dynamic " + // allow:dynamic-require — diagnostic message text
|
|
136
|
+
"require(variable) breaks SEA / esbuild bundling."); // allow:dynamic-require — diagnostic message text
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Module-shape gate
|
|
140
|
+
if (!mod || !Buffer.isBuffer(mod.payload) || !mod.metadata) {
|
|
141
|
+
throw new VendorDataError("vendor-data/bad-shape",
|
|
142
|
+
"vendorData: '" + name + "' .data.js missing payload Buffer or metadata. " +
|
|
143
|
+
"File is hand-edited or corrupted; re-run vendor-update.sh --refresh-data.");
|
|
144
|
+
}
|
|
145
|
+
var meta = mod.metadata;
|
|
146
|
+
if (typeof meta.sha256 !== "string" || typeof meta.sha3_512 !== "string" ||
|
|
147
|
+
typeof meta.signatureB64 !== "string") {
|
|
148
|
+
throw new VendorDataError("vendor-data/bad-metadata",
|
|
149
|
+
"vendorData: '" + name + "' metadata missing sha256 / sha3_512 / signatureB64. " +
|
|
150
|
+
"File is hand-edited or corrupted; re-run vendor-update.sh --refresh-data.");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Layer 1: SHA-256 self-verify
|
|
154
|
+
var actual256 = nodeCrypto.createHash("sha256").update(mod.payload).digest("hex");
|
|
155
|
+
if (actual256 !== meta.sha256) {
|
|
156
|
+
throw new VendorDataError("vendor-data/sha256-mismatch",
|
|
157
|
+
"vendorData: '" + name + "' SHA-256 mismatch — payload tampered. " +
|
|
158
|
+
"expected=" + meta.sha256.slice(0, 12) + "… got=" + actual256.slice(0, 12) + "…");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Layer 2: SHA3-512 self-verify
|
|
162
|
+
var actual3 = nodeCrypto.createHash("sha3-512").update(mod.payload).digest("hex");
|
|
163
|
+
if (actual3 !== meta.sha3_512) {
|
|
164
|
+
throw new VendorDataError("vendor-data/sha3-512-mismatch",
|
|
165
|
+
"vendorData: '" + name + "' SHA3-512 mismatch — payload tampered. " +
|
|
166
|
+
"expected=" + meta.sha3_512.slice(0, 12) + "… got=" + actual3.slice(0, 12) + "…");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Layer 3: SLH-DSA-SHAKE-256f signature verify against maintainer pubkey
|
|
170
|
+
var sigBytes = Buffer.from(meta.signatureB64, "base64");
|
|
171
|
+
var pubkeyBytes = _pemToRaw(PUBKEY_PEM);
|
|
172
|
+
var slh = pqcSoftware.slh_dsa_shake_256f;
|
|
173
|
+
var sigOk = false;
|
|
174
|
+
try {
|
|
175
|
+
// noble API: verify(signature, message, publicKey)
|
|
176
|
+
sigOk = slh.verify(sigBytes, mod.payload, pubkeyBytes);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
throw new VendorDataError("vendor-data/signature-verify-error",
|
|
179
|
+
"vendorData: '" + name + "' SLH-DSA-SHAKE-256f verify threw: " +
|
|
180
|
+
(e && e.message ? e.message : "unknown error"));
|
|
181
|
+
}
|
|
182
|
+
if (!sigOk) {
|
|
183
|
+
throw new VendorDataError("vendor-data/signature-invalid",
|
|
184
|
+
"vendorData: '" + name + "' SLH-DSA-SHAKE-256f signature INVALID — " +
|
|
185
|
+
"payload not signed by maintainer pubkey (fingerprint " +
|
|
186
|
+
meta.publicKeyFingerprint + "). An attacker has swapped content + " +
|
|
187
|
+
"forged hashes but cannot forge the signature without the maintainer " +
|
|
188
|
+
"private key. Stop the framework and audit the install path immediately.");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Layer 4: canary check (always-on, runs per get() not only at verifyAll).
|
|
192
|
+
// For entries with a registered canary, the .data.js exports a
|
|
193
|
+
// canaryCheck closure that scans the raw payload for the expected
|
|
194
|
+
// token. Refuses to return the bytes if the canary is absent.
|
|
195
|
+
if (entry.canary !== null) {
|
|
196
|
+
if (typeof mod.canaryCheck !== "function" || mod.canaryCheck() !== true) {
|
|
197
|
+
throw new VendorDataError("vendor-data/canary-absent",
|
|
198
|
+
"vendorData: '" + name + "' canary '" + entry.canary +
|
|
199
|
+
"' NOT FOUND in payload. An attacker has swapped data bytes with " +
|
|
200
|
+
"correctly-forged hashes + signatures but failed to preserve the " +
|
|
201
|
+
"canary token the framework expects.");
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_payloadCache[name] = mod.payload;
|
|
206
|
+
return mod.payload;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// _pemToRaw — extract the raw SPKI bytes from a PEM-wrapped public key.
|
|
210
|
+
// The .vendor-data-pubkey file ships as PEM (BEGIN PUBLIC KEY ... END
|
|
211
|
+
// PUBLIC KEY); the SLH-DSA verifier expects raw bytes. We strip the
|
|
212
|
+
// header/footer + decode base64. Defensive — refuses anything that
|
|
213
|
+
// doesn't look like the expected PEM shape.
|
|
214
|
+
function _pemToRaw(pem) {
|
|
215
|
+
var lines = pem.replace(/\r/g, "").split("\n");
|
|
216
|
+
if (lines[0].indexOf("-----BEGIN ") !== 0) {
|
|
217
|
+
throw new VendorDataError("vendor-data/pubkey-bad-pem",
|
|
218
|
+
"vendorData: inlined pubkey module is not PEM-shaped (lib/vendor/vendor-data-pubkey.js corrupted; re-run scripts/vendor-data-keygen.js)");
|
|
219
|
+
}
|
|
220
|
+
var body = "";
|
|
221
|
+
for (var i = 1; i < lines.length; i++) {
|
|
222
|
+
if (lines[i].indexOf("-----END ") === 0) break;
|
|
223
|
+
body += lines[i];
|
|
224
|
+
}
|
|
225
|
+
return Buffer.from(body, "base64");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @primitive b.vendorData.get
|
|
230
|
+
* @signature b.vendorData.get(name)
|
|
231
|
+
* @since 0.9.8
|
|
232
|
+
* @status stable
|
|
233
|
+
* @related b.vendorData.verifyAll, b.vendorData.inventory
|
|
234
|
+
*
|
|
235
|
+
* Return the verified payload Buffer for the named vendored data file.
|
|
236
|
+
* First call per name runs all integrity layers (dual-hash + SLH-DSA
|
|
237
|
+
* signature); subsequent calls return from cache. The canary-in-payload
|
|
238
|
+
* check is run by `verifyAll()` at framework boot; `get()` skips it on
|
|
239
|
+
* the hot path because the canary's parse-side semantics are caller-
|
|
240
|
+
* specific (PSL parser vs password-set lookup vs PEM chain).
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* var pslBytes = b.vendorData.get("public-suffix-list");
|
|
244
|
+
* var psl = pslBytes.toString("utf8");
|
|
245
|
+
*/
|
|
246
|
+
function get(name) {
|
|
247
|
+
return _loadAndVerify(name);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @primitive b.vendorData.getAsString
|
|
252
|
+
* @signature b.vendorData.getAsString(name)
|
|
253
|
+
* @since 0.9.8
|
|
254
|
+
* @status stable
|
|
255
|
+
* @related b.vendorData.get
|
|
256
|
+
*
|
|
257
|
+
* Convenience wrapper around `get(name)` that returns the payload
|
|
258
|
+
* decoded as UTF-8. Use when the caller wants a string directly; the
|
|
259
|
+
* underlying Buffer caches once so repeated calls don't re-decode.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* var passwordList = b.vendorData.getAsString("common-passwords-top-10000");
|
|
263
|
+
* var lines = passwordList.split(/\r?\n/);
|
|
264
|
+
*/
|
|
265
|
+
function getAsString(name) {
|
|
266
|
+
return _loadAndVerify(name).toString("utf8");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* @primitive b.vendorData.verifyAll
|
|
271
|
+
* @signature b.vendorData.verifyAll()
|
|
272
|
+
* @since 0.9.8
|
|
273
|
+
* @status stable
|
|
274
|
+
* @related b.vendorData.get, b.vendorData.inventory
|
|
275
|
+
*
|
|
276
|
+
* Run all four integrity layers across every registered vendored data
|
|
277
|
+
* file — including the in-payload canary check via the caller-supplied
|
|
278
|
+
* canaryCheck closure each `.data.js` exports. Returns the inventory
|
|
279
|
+
* of names verified. Throws on any failure. Operators wire this into
|
|
280
|
+
* framework boot so a tampered install fails fast.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* b.vendorData.verifyAll(); // throws VendorDataError on any tamper
|
|
284
|
+
*/
|
|
285
|
+
function verifyAll() {
|
|
286
|
+
var names = Object.keys(KNOWN_VENDOR_DATA);
|
|
287
|
+
for (var i = 0; i < names.length; i++) {
|
|
288
|
+
// _loadAndVerify runs all four layers (sha256 + sha3-512 +
|
|
289
|
+
// SLH-DSA signature + canary). verifyAll() now just forces
|
|
290
|
+
// eager-load of every registered entry — useful in tests and
|
|
291
|
+
// for operators wanting "verify everything upfront at boot"
|
|
292
|
+
// semantics even before any caller touches a specific entry.
|
|
293
|
+
_loadAndVerify(names[i]);
|
|
294
|
+
}
|
|
295
|
+
return names.slice();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @primitive b.vendorData.inventory
|
|
300
|
+
* @signature b.vendorData.inventory()
|
|
301
|
+
* @since 0.9.8
|
|
302
|
+
* @status stable
|
|
303
|
+
* @related b.vendorData.verifyAll
|
|
304
|
+
*
|
|
305
|
+
* Return per-vendor-data metadata for compliance reporting. Each
|
|
306
|
+
* entry: `{ name, source, fetchedAt, sha256, sha3_512, signedBy,
|
|
307
|
+
* canary, byteLength }`. Pipes directly into SBOM emission +
|
|
308
|
+
* b.compliance posture rendering.
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* var inv = b.vendorData.inventory();
|
|
312
|
+
* inv.forEach(function (entry) {
|
|
313
|
+
* console.log(entry.name + " (" + entry.byteLength + " bytes) " +
|
|
314
|
+
* "fetched " + entry.fetchedAt + " from " + entry.source +
|
|
315
|
+
* " — signed by " + entry.signedBy);
|
|
316
|
+
* });
|
|
317
|
+
*/
|
|
318
|
+
function inventory() {
|
|
319
|
+
var out = [];
|
|
320
|
+
var names = Object.keys(KNOWN_VENDOR_DATA);
|
|
321
|
+
for (var i = 0; i < names.length; i++) {
|
|
322
|
+
var name = names[i];
|
|
323
|
+
var entry = KNOWN_VENDOR_DATA[name];
|
|
324
|
+
_loadAndVerify(name);
|
|
325
|
+
var mod = _MODULES[name];
|
|
326
|
+
var meta = mod.metadata;
|
|
327
|
+
out.push({
|
|
328
|
+
name: name,
|
|
329
|
+
source: meta.source,
|
|
330
|
+
fetchedAt: meta.fetchedAt,
|
|
331
|
+
license: meta.license,
|
|
332
|
+
sha256: meta.sha256,
|
|
333
|
+
sha3_512: meta.sha3_512,
|
|
334
|
+
signedBy: meta.publicKeyFingerprint,
|
|
335
|
+
canary: entry.canary,
|
|
336
|
+
byteLength: mod.payload.length,
|
|
337
|
+
description: entry.description,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
return out;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Eager verification at module-load. The first time anything
|
|
344
|
+
// require()s b.vendorData (e.g. lib/public-suffix.js, lib/auth/
|
|
345
|
+
// password.js, lib/mail-bimi.js — all of which load early in any
|
|
346
|
+
// framework consumer's import graph), every registered vendor data
|
|
347
|
+
// file is dual-hash + signature + canary-verified before any caller
|
|
348
|
+
// gets the chance to call get(). Tamper = fail-fast at boot, not at
|
|
349
|
+
// first-request-touches-PSL surprise. Operators wanting to defer
|
|
350
|
+
// verification (e.g. test rigs that mock require() resolution) set
|
|
351
|
+
// BLAMEJS_VENDOR_DATA_DEFER_BOOT_VERIFY=1 in the environment.
|
|
352
|
+
if (safeEnv.readVar("BLAMEJS_VENDOR_DATA_DEFER_BOOT_VERIFY", { default: "" }) !== "1") {
|
|
353
|
+
verifyAll();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
module.exports = {
|
|
357
|
+
get: get,
|
|
358
|
+
getAsString: getAsString,
|
|
359
|
+
verifyAll: verifyAll,
|
|
360
|
+
inventory: inventory,
|
|
361
|
+
KNOWN_VENDOR_DATA: KNOWN_VENDOR_DATA,
|
|
362
|
+
VendorDataError: VendorDataError,
|
|
363
|
+
};
|
package/package.json
CHANGED
package/sbom.cdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
|
3
3
|
"bomFormat": "CycloneDX",
|
|
4
4
|
"specVersion": "1.6",
|
|
5
|
-
"serialNumber": "urn:uuid:
|
|
5
|
+
"serialNumber": "urn:uuid:cd59dfcc-1a4e-488c-b7fa-8f4b9ac61c45",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-05-
|
|
8
|
+
"timestamp": "2026-05-13T14:31:49.840Z",
|
|
9
9
|
"lifecycles": [
|
|
10
10
|
{
|
|
11
11
|
"phase": "build"
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"component": {
|
|
22
|
-
"bom-ref": "@blamejs/core@0.9.
|
|
22
|
+
"bom-ref": "@blamejs/core@0.9.9",
|
|
23
23
|
"type": "library",
|
|
24
24
|
"name": "blamejs",
|
|
25
|
-
"version": "0.9.
|
|
25
|
+
"version": "0.9.9",
|
|
26
26
|
"scope": "required",
|
|
27
27
|
"author": "blamejs contributors",
|
|
28
28
|
"description": "The Node framework that owns its stack.",
|
|
29
|
-
"purl": "pkg:npm/%40blamejs/core@0.9.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/core@0.9.9",
|
|
30
30
|
"properties": [],
|
|
31
31
|
"externalReferences": [
|
|
32
32
|
{
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"components": [],
|
|
55
55
|
"dependencies": [
|
|
56
56
|
{
|
|
57
|
-
"ref": "@blamejs/core@0.9.
|
|
57
|
+
"ref": "@blamejs/core@0.9.9",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|