@blamejs/core 0.15.31 → 0.15.33
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 +4 -0
- package/lib/acme.js +1 -1
- package/lib/agent-trace.js +1 -1
- package/lib/app-shutdown.js +2 -2
- package/lib/arg-parser.js +3 -3
- package/lib/auth/fido-mds3.js +1 -1
- package/lib/auth/oauth.js +2 -2
- package/lib/cert.js +1 -1
- package/lib/cli.js +2 -2
- package/lib/cluster.js +1 -1
- package/lib/db-schema.js +1 -1
- package/lib/gate-contract.js +1 -1
- package/lib/json-schema.js +2 -2
- package/lib/mail-send-deliver.js +1 -1
- package/lib/mcp.js +1 -1
- package/lib/middleware/csrf-protect.js +1 -1
- package/lib/module-loader.js +2 -2
- package/lib/network-dns-resolver.js +1 -1
- package/lib/network-smtp-policy.js +1 -1
- package/lib/pqc-gate.js +1 -1
- package/lib/retry.js +1 -1
- package/lib/safe-url.js +1 -1
- package/lib/ssrf-guard.js +1 -1
- package/lib/vault-aad.js +1 -1
- package/lib/vendor-data.js +2 -2
- package/lib/websocket.js +1 -1
- package/lib/ws-client.js +3 -3
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.15.x
|
|
10
10
|
|
|
11
|
+
- v0.15.33 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** Three more suppression classes in the codebase-patterns guard suite were re-verified from scratch and renamed to descriptive tokens, with their old names recorded as retired and their in-source marker comments updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Three more suppression-marker classes re-verified and their tokens retired* — Continuing the re-verification pass: each marked site for the math-random-noncrypto, raw-new-url, and dynamic-require guard classes was re-read and confirmed (non-security jitter/sampling; URL parsing for shape/origin inspection or behind the safe wrapper; operator-supplied module loads), then the class was renamed to a descriptive token and its old name added to the retired-token set. This is test-suite tooling; no shipped framework behavior changed.
|
|
12
|
+
|
|
13
|
+
- v0.15.32 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** Three more suppression classes in the codebase-patterns guard suite were re-verified from scratch and renamed to descriptive tokens, with their old names recorded as retired so the prior approval cannot be silently resurrected and their in-source marker comments updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Three more suppression-marker classes re-verified and their tokens retired* — Continuing the re-verification pass: each marked site for the process-exit, hand-rolled buffer-collect, and raw-outbound-http guard classes was re-read and confirmed (operator-opt-in exits; bounded protocol-framing / TLV assembly; framework-routed outbound calls), then the class was renamed to a descriptive token and its old name added to the retired-token set. This is test-suite tooling; no shipped framework behavior changed.
|
|
14
|
+
|
|
11
15
|
- v0.15.31 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** The codebase-patterns guard suite gains a gate that retires a renamed suppression-marker token: once a suppression class is re-verified and renamed, its old token cannot be silently re-registered, so a later suppression has to be re-examined under the new name instead of inheriting a stale approval. Eight suppression classes were re-verified and renamed to descriptive tokens this release, and their in-source marker comments were updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Re-verification gate retires a renamed suppression-marker token* — A new guard refuses to re-register a retired suppression-marker token, and the orphan check points a stale marker at its current name. When a suppression class is re-verified, it is renamed to a descriptive token and the old name is recorded as retired, so the old approval cannot be quietly resurrected — a future suppression must be re-examined and re-stamped under the new name. This is test-suite tooling; no shipped framework behavior changed.
|
|
12
16
|
|
|
13
17
|
- v0.15.30 (2026-06-26) — **Importing the webhook module for inbound signature verification no longer pulls the Node HTTP client (or its `node:http` / `node:https` / `node:http2` chain), so `b.webhook.verify` runs in a Worker / edge runtime when the module is imported directly.** lib/webhook and its delivery store eagerly required the outbound HTTP client at module load — directly, and transitively through the persistence-backed dispatcher — so importing the webhook module threw in a Cloudflare Workers / edge runtime that has no node:http / node:net / node:tls, even though b.webhook.verify needs only HMAC-SHA-256 and a timing-safe compare. The HTTP client and the SQL-backed dispatcher are now resolved lazily, only on the outbound send / dispatch paths; importing the module for inbound verification loads no Node networking module. Verified by asserting no networking builtin appears in process.moduleLoadList on the verify path. The framework's aggregate entry point still initializes the networking stack eagerly, so the edge verify path is the webhook module imported directly rather than the aggregate b namespace. **Fixed:** *Inbound webhook verification loads without the Node networking stack (Worker / edge runtime)* — The webhook module and its dispatcher delivery store required the outbound HTTP client (node:http / node:https / node:http2) at module load, so importing the module threw in a runtime without those builtins — even though b.webhook.verify is HMAC-SHA-256 plus a timing-safe compare and the dispatcher (SQL-backed persistence) is only needed for outbound delivery. The HTTP client and the dispatcher are now resolved lazily, on the outbound send / dispatch paths only; the inbound verify path loads no Node networking module. An edge handler that imports the webhook module directly can pre-verify an inbound Stripe webhook signature with the primitive's hardening (Stripe-Signature size cap, v1-hex anti-DoS cap, minimum-tolerance floor, optional atomic replay store) instead of hand-rolling the t=/v1= parse, tolerance window, and timing-safe compare. The framework's aggregate entry still loads the networking stack eagerly; import the webhook module directly for the edge verify path.
|
package/lib/acme.js
CHANGED
|
@@ -1026,7 +1026,7 @@ function create(opts) {
|
|
|
1026
1026
|
// Non-crypto: RFC 9773 §4.2 fleet-scheduling jitter inside the
|
|
1027
1027
|
// CA-suggested renewal window. Predictability is not a threat
|
|
1028
1028
|
// here; uniform distribution across the window is the goal.
|
|
1029
|
-
renewAtMs = jLo + Math.floor(Math.random() * (jHi - jLo + 1)); // allow:math-random-noncrypto — RFC 9773 fleet jitter, predictability not a threat
|
|
1029
|
+
renewAtMs = jLo + Math.floor(Math.random() * (jHi - jLo + 1)); // allow:math-random-noncrypto-jitter-sampling — RFC 9773 fleet jitter, predictability not a threat
|
|
1030
1030
|
} else {
|
|
1031
1031
|
// Past-window — renew immediately, no jitter.
|
|
1032
1032
|
renewAtMs = nowMs;
|
package/lib/agent-trace.js
CHANGED
|
@@ -256,7 +256,7 @@ function _shouldSample(globalRate, perMethod, method, traceId) {
|
|
|
256
256
|
// No trace-id supplied — start of a new trace. Operators wire
|
|
257
257
|
// shouldSample(method, ctx.traceId) on every downstream hop so
|
|
258
258
|
// children inherit the decision deterministically.
|
|
259
|
-
return Math.random() < rate; // allow:math-random-noncrypto — start-of-trace seed only; downstream hops pass traceId for deterministic propagation
|
|
259
|
+
return Math.random() < rate; // allow:math-random-noncrypto-jitter-sampling — start-of-trace seed only; downstream hops pass traceId for deterministic propagation
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
function _formatAttributes(info) {
|
package/lib/app-shutdown.js
CHANGED
|
@@ -247,7 +247,7 @@ function create(opts) {
|
|
|
247
247
|
var exitCode = (process.exitCode !== undefined && process.exitCode !== 0)
|
|
248
248
|
? process.exitCode : (allOk ? 0 : 1);
|
|
249
249
|
setImmediate(function () {
|
|
250
|
-
// allow:process-exit — operator opted into exitAfterPhases,
|
|
250
|
+
// allow:process-exit-operator-optin — operator opted into exitAfterPhases,
|
|
251
251
|
// delegating process lifecycle to the orchestrator
|
|
252
252
|
process.exit(exitCode);
|
|
253
253
|
});
|
|
@@ -280,7 +280,7 @@ function create(opts) {
|
|
|
280
280
|
// Bounded forced exit after the grace deadline, armed ONLY inside the
|
|
281
281
|
// signal handler (operator opted into installSignalHandlers,
|
|
282
282
|
// delegating process lifecycle to the orchestrator).
|
|
283
|
-
// allow:process-exit — operator-delegated lifecycle, watchdog only
|
|
283
|
+
// allow:process-exit-operator-optin — operator-delegated lifecycle, watchdog only
|
|
284
284
|
process.exit(process.exitCode || 1);
|
|
285
285
|
}, graceMs + forceExitMarginMs);
|
|
286
286
|
if (typeof watchdog.unref === "function") watchdog.unref();
|
package/lib/arg-parser.js
CHANGED
|
@@ -550,7 +550,7 @@ function create(opts) {
|
|
|
550
550
|
// `<prog> help [<cmd>]`
|
|
551
551
|
var topic = (split.rest && split.rest.length > 0) ? split.rest[0] : null;
|
|
552
552
|
var msg = topic && commandsByName[topic] ? help(topic) : help();
|
|
553
|
-
if (exitOnHelp) { stdout.write(msg + "\n"); process.exit(0); } // allow:process-exit — explicit { exit: true } from a bin/ shim
|
|
553
|
+
if (exitOnHelp) { stdout.write(msg + "\n"); process.exit(0); } // allow:process-exit-operator-optin — explicit { exit: true } from a bin/ shim
|
|
554
554
|
return { command: null, flags: {}, positionals: [], helpRequested: true, helpText: msg };
|
|
555
555
|
}
|
|
556
556
|
|
|
@@ -582,7 +582,7 @@ function create(opts) {
|
|
|
582
582
|
|
|
583
583
|
if (cmdParsed.helpRequested || preParsed.helpRequested) {
|
|
584
584
|
var cmsg = _renderCommandHelp(parser, cmdEntry);
|
|
585
|
-
if (exitOnHelp) { stdout.write(cmsg + "\n"); process.exit(0); } // allow:process-exit — explicit { exit: true } from a bin/ shim
|
|
585
|
+
if (exitOnHelp) { stdout.write(cmsg + "\n"); process.exit(0); } // allow:process-exit-operator-optin — explicit { exit: true } from a bin/ shim
|
|
586
586
|
return { command: cmdEntry.name, flags: {}, positionals: [], helpRequested: true, helpText: cmsg };
|
|
587
587
|
}
|
|
588
588
|
|
|
@@ -606,7 +606,7 @@ function create(opts) {
|
|
|
606
606
|
// as a flag-only parser. Honor `--` and aggregate everything else.
|
|
607
607
|
if (preParsed.helpRequested) {
|
|
608
608
|
var hmsg = _renderHelp(parser);
|
|
609
|
-
if (exitOnHelp) { stdout.write(hmsg + "\n"); process.exit(0); } // allow:process-exit — explicit { exit: true } from a bin/ shim
|
|
609
|
+
if (exitOnHelp) { stdout.write(hmsg + "\n"); process.exit(0); } // allow:process-exit-operator-optin — explicit { exit: true } from a bin/ shim
|
|
610
610
|
return { command: null, flags: {}, positionals: [], helpRequested: true, helpText: hmsg };
|
|
611
611
|
}
|
|
612
612
|
_applyDefaultsAndRequired(parser.flags.list, preParsed.flags, "top-level");
|
package/lib/auth/fido-mds3.js
CHANGED
|
@@ -420,7 +420,7 @@ function _verifyAndParseBlob(token) {
|
|
|
420
420
|
* typeof blob.entries.length === "number";
|
|
421
421
|
* // → true
|
|
422
422
|
*/
|
|
423
|
-
async function fetch(opts) { // allow:raw-outbound-http — function name is fetch, internal call routes through b.httpClient
|
|
423
|
+
async function fetch(opts) { // allow:raw-outbound-http-framework-internal — function name is fetch, internal call routes through b.httpClient
|
|
424
424
|
opts = opts || {};
|
|
425
425
|
validateOpts(opts, ["url", "caCertificate", "force", "timeoutMs"], "auth.fido_mds3.fetch");
|
|
426
426
|
|
package/lib/auth/oauth.js
CHANGED
|
@@ -282,7 +282,7 @@ function _validateUrl(url, allowHttp, label) {
|
|
|
282
282
|
// global flag.
|
|
283
283
|
var isLocalhostHttp = false;
|
|
284
284
|
try {
|
|
285
|
-
var parsed = new URL(url); // allow:raw-new-url — RFC 9700 §4.1.1 localhost-exception lookup; safeUrl re-validates below for non-localhost paths
|
|
285
|
+
var parsed = new URL(url); // allow:raw-new-url-parse-only — RFC 9700 §4.1.1 localhost-exception lookup; safeUrl re-validates below for non-localhost paths
|
|
286
286
|
// Strip trailing root-zone dot before the localhost compare.
|
|
287
287
|
// RFC 1034 §3.1 — `localhost.` resolves identically to `localhost`;
|
|
288
288
|
// without the strip, an attacker who registers `evil.com` as a
|
|
@@ -2168,7 +2168,7 @@ function create(opts) {
|
|
|
2168
2168
|
"parseFrontchannelLogoutRequest: req with url required");
|
|
2169
2169
|
}
|
|
2170
2170
|
var u;
|
|
2171
|
-
try { u = new URL(req.url, "http://placeholder.invalid"); } // allow:raw-new-url — req.url is the framework-normalized path; placeholder base provides a synthetic origin for relative-path parse
|
|
2171
|
+
try { u = new URL(req.url, "http://placeholder.invalid"); } // allow:raw-new-url-parse-only — req.url is the framework-normalized path; placeholder base provides a synthetic origin for relative-path parse
|
|
2172
2172
|
catch (_e) {
|
|
2173
2173
|
throw new OAuthError("auth-oauth/bad-frontchannel-logout-url",
|
|
2174
2174
|
"parseFrontchannelLogoutRequest: malformed request URL");
|
package/lib/cert.js
CHANGED
|
@@ -721,7 +721,7 @@ function create(opts) {
|
|
|
721
721
|
var chain = _splitPemChain(ctx.cert);
|
|
722
722
|
if (chain.length < 2) return; // no issuer in the served chain
|
|
723
723
|
try {
|
|
724
|
-
// allow:raw-outbound-http — b.network.tls.ocsp.fetch composes b.httpClient internally (SSRF guard + pinned DNS); not a raw outbound call
|
|
724
|
+
// allow:raw-outbound-http-framework-internal — b.network.tls.ocsp.fetch composes b.httpClient internally (SSRF guard + pinned DNS); not a raw outbound call
|
|
725
725
|
var rv = await networkTls().ocsp.fetch({ leafPem: chain[0], issuerPem: chain[1] });
|
|
726
726
|
ctx.ocspResponse = rv.ocspDer;
|
|
727
727
|
_emitAudit("cert.ocsp.refreshed", "success", { name: name });
|
package/lib/cli.js
CHANGED
|
@@ -455,11 +455,11 @@ function _resolveTargetModule(modulePath, ctx) {
|
|
|
455
455
|
// code never reaches this nodePath.
|
|
456
456
|
if (!modulePath) {
|
|
457
457
|
var root = nodePath.resolve(__dirname, "..");
|
|
458
|
-
return require(nodePath.join(root, "index.js")); // allow:dynamic-require — operator-extensibility entry point
|
|
458
|
+
return require(nodePath.join(root, "index.js")); // allow:dynamic-require-operator-module — operator-extensibility entry point
|
|
459
459
|
}
|
|
460
460
|
var abs = nodePath.isAbsolute(modulePath) ? modulePath : nodePath.resolve(ctx.cwd, modulePath);
|
|
461
461
|
delete require.cache[require.resolve(abs)];
|
|
462
|
-
return require(abs); // allow:dynamic-require — operator-extensibility entry point
|
|
462
|
+
return require(abs); // allow:dynamic-require-operator-module — operator-extensibility entry point
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
function _runApiSnapshot(args, ctx) {
|
package/lib/cluster.js
CHANGED
|
@@ -750,7 +750,7 @@ async function _heartbeat() {
|
|
|
750
750
|
// budget is in `leaseTtl - heartbeatMs`, not in the jitter
|
|
751
751
|
// window).
|
|
752
752
|
if (!lease) {
|
|
753
|
-
var jitterMs = Math.floor(Math.random() * (heartbeatMs * 0.4)); // allow:math-random-noncrypto — heartbeat jitter, not security-bearing
|
|
753
|
+
var jitterMs = Math.floor(Math.random() * (heartbeatMs * 0.4)); // allow:math-random-noncrypto-jitter-sampling — heartbeat jitter, not security-bearing
|
|
754
754
|
if (jitterMs > 0) {
|
|
755
755
|
await safeAsync.sleep(jitterMs);
|
|
756
756
|
}
|
package/lib/db-schema.js
CHANGED
|
@@ -605,7 +605,7 @@ function runMigrations(database, migrationDir) {
|
|
|
605
605
|
// Operator-supplied migration file — by definition not statically
|
|
606
606
|
// require-able by a bundler. Anyone bundling this surface into SEA
|
|
607
607
|
// accepts that runtime migration loading won't resolve.
|
|
608
|
-
mig = require(fullPath); // allow:dynamic-require — operator-supplied migration
|
|
608
|
+
mig = require(fullPath); // allow:dynamic-require-operator-module — operator-supplied migration
|
|
609
609
|
} catch (e) {
|
|
610
610
|
throw new Error("migration '" + file + "' failed to load: " + e.message);
|
|
611
611
|
}
|
package/lib/gate-contract.js
CHANGED
|
@@ -940,7 +940,7 @@ function canaryGate(gate, opts) {
|
|
|
940
940
|
name: opts.name || "canary",
|
|
941
941
|
check: async function (ctx) {
|
|
942
942
|
var d = await gate.check(ctx);
|
|
943
|
-
if (d.action === "refuse" && Math.random() > rate) { // allow:math-random-noncrypto — canary sampling, non-security
|
|
943
|
+
if (d.action === "refuse" && Math.random() > rate) { // allow:math-random-noncrypto-jitter-sampling — canary sampling, non-security
|
|
944
944
|
return Object.assign({}, d, { ok: true, action: "warn" });
|
|
945
945
|
}
|
|
946
946
|
return d;
|
package/lib/json-schema.js
CHANGED
|
@@ -104,7 +104,7 @@ function _resolveUri(ref, base) {
|
|
|
104
104
|
// RFC 3986 relative→absolute resolution of a schema $id/$ref (operator-
|
|
105
105
|
// trusted schema text, not request data); safeUrl.parse intentionally
|
|
106
106
|
// rejects the relative refs and non-http schemes schemas legitimately use.
|
|
107
|
-
try { return new URL(ref, base).href; } // allow:raw-new-url — schema $id/$ref URI resolution, not request-data URL handling
|
|
107
|
+
try { return new URL(ref, base).href; } // allow:raw-new-url-parse-only — schema $id/$ref URI resolution, not request-data URL handling
|
|
108
108
|
catch (_e) {
|
|
109
109
|
// Relative resolution against a non-URL base (e.g. "urn:..." or a
|
|
110
110
|
// bare name). Fall back to fragment-aware concatenation.
|
|
@@ -730,7 +730,7 @@ function _checkFormat(format, value, type) {
|
|
|
730
730
|
if (/\s/.test(value)) return false; // raw whitespace is not a valid URI
|
|
731
731
|
if (/%(?![0-9A-Fa-f]{2})/.test(value)) return false; // malformed percent-escape
|
|
732
732
|
if (!/^[A-Za-z][A-Za-z0-9+.-]*:/.test(value)) return false; // absolute URI requires a scheme // allow:regex-no-length-cap — linear scheme prefix
|
|
733
|
-
try { new URL(value); return true; } catch (_e) { return false; } // allow:raw-new-url — string-shape check, no fetch / SSRF surface
|
|
733
|
+
try { new URL(value); return true; } catch (_e) { return false; } // allow:raw-new-url-parse-only — string-shape check, no fetch / SSRF surface
|
|
734
734
|
}
|
|
735
735
|
case "uuid": return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(value); // allow:regex-no-length-cap — fixed-width UUID
|
|
736
736
|
case "ipv4": return /^(\d{1,3}\.){3}\d{1,3}$/.test(value) && value.split(".").every(function (o) { return Number(o) <= 255; }); // allow:regex-no-length-cap — bounded dotted-quad
|
package/lib/mail-send-deliver.js
CHANGED
|
@@ -213,7 +213,7 @@ async function _applyMtaStsPolicy(domain, mxs, policyMode, auditEmit) {
|
|
|
213
213
|
if (policyMode === "off") return mxs;
|
|
214
214
|
var sts;
|
|
215
215
|
try {
|
|
216
|
-
sts = await smtpPolicy().mtaSts.fetch(domain); // allow:raw-outbound-http — method call on b.network.smtp.policy wrapper, not a raw `fetch(`
|
|
216
|
+
sts = await smtpPolicy().mtaSts.fetch(domain); // allow:raw-outbound-http-framework-internal — method call on b.network.smtp.policy wrapper, not a raw `fetch(`
|
|
217
217
|
} catch (e) {
|
|
218
218
|
if (policyMode === "enforce") {
|
|
219
219
|
throw new DeliverError("deliver/mta-sts-fetch-failed",
|
package/lib/mcp.js
CHANGED
|
@@ -510,7 +510,7 @@ function _toolResultSanitize(result, opts) {
|
|
|
510
510
|
} else if (block.type === "image" || block.type === "resource_link" || block.type === "audio") {
|
|
511
511
|
var url = block.url || (block.resource && block.resource.uri);
|
|
512
512
|
if (typeof url === "string" && url.length > 0 && allowedHosts.length > 0) {
|
|
513
|
-
var u; try { u = new URL(url); } catch (_e) { u = null; } // allow:raw-new-url — operator-supplied tool URL; allowlist enforced below
|
|
513
|
+
var u; try { u = new URL(url); } catch (_e) { u = null; } // allow:raw-new-url-parse-only — operator-supplied tool URL; allowlist enforced below
|
|
514
514
|
if (!u || allowedHosts.indexOf(u.host) === -1) {
|
|
515
515
|
issues.push({ kind: "off-allowlist-url", index: i, url: url });
|
|
516
516
|
if (posture === "sanitize") continue; // drop the block in sanitize mode
|
|
@@ -194,7 +194,7 @@ function _checkOriginAllowed(req, allowedOrigins, isHttpsFn, requireOrigin) {
|
|
|
194
194
|
|
|
195
195
|
function _originOf(rawUrl) {
|
|
196
196
|
try {
|
|
197
|
-
var u = new URL(rawUrl); // allow:raw-new-url — origin-shape inspection (NOT outbound). Intentionally tolerates file:// / data: which safeUrl.parse refuses.
|
|
197
|
+
var u = new URL(rawUrl); // allow:raw-new-url-parse-only — origin-shape inspection (NOT outbound). Intentionally tolerates file:// / data: which safeUrl.parse refuses.
|
|
198
198
|
return u.origin; // "https://host:port" — no path / query / fragment
|
|
199
199
|
} catch (_e) { return null; }
|
|
200
200
|
}
|
package/lib/module-loader.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* operator-supplied module file (a migration or a seed) by path.
|
|
5
5
|
*
|
|
6
6
|
* Operator modules execute arbitrary code on `require`, so the dynamic
|
|
7
|
-
* `require()` lives here behind ONE `allow:dynamic-require` marker rather
|
|
7
|
+
* `require()` lives here behind ONE `allow:dynamic-require-operator-module` marker rather
|
|
8
8
|
* than scattered across every host-CLI loader (`b.migrations`,
|
|
9
9
|
* `b.seeders`, `b.externalDb.migrate`). The require cache is busted first
|
|
10
10
|
* so a dev / test rewriting a fixture between calls picks up the new
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
function requireFresh(absPath, onLoadError) {
|
|
34
34
|
try { delete require.cache[require.resolve(absPath)]; } catch (_e) { /* not yet cached */ }
|
|
35
35
|
try {
|
|
36
|
-
return require(absPath); // allow:dynamic-require — operator-supplied module (migration / seed)
|
|
36
|
+
return require(absPath); // allow:dynamic-require-operator-module — operator-supplied module (migration / seed)
|
|
37
37
|
} catch (e) {
|
|
38
38
|
throw onLoadError(e);
|
|
39
39
|
}
|
|
@@ -488,7 +488,7 @@ async function _wireLookup(name, qtype, timeoutMs) {
|
|
|
488
488
|
// Raw DoH wire-format request — bypasses b.httpClient envelope
|
|
489
489
|
// because we need the raw binary response bytes for safeDns to
|
|
490
490
|
// parse (httpClient assumes JSON/text shapes).
|
|
491
|
-
var req = https.request({ // allow:raw-outbound-http — DoH wire-format response bytes; b.httpClient envelopes assume text/JSON, and httpClient → ssrfGuard → DNS → DoH would form a cycle
|
|
491
|
+
var req = https.request({ // allow:raw-outbound-http-framework-internal — DoH wire-format response bytes; b.httpClient envelopes assume text/JSON, and httpClient → ssrfGuard → DNS → DoH would form a cycle
|
|
492
492
|
hostname: u.hostname,
|
|
493
493
|
port: u.port || 443, // HTTPS port
|
|
494
494
|
path: u.pathname + u.search,
|
|
@@ -660,7 +660,7 @@ async function tlsRptSubmit(report, opts) {
|
|
|
660
660
|
try {
|
|
661
661
|
if (/^https:\/\//i.test(uri)) {
|
|
662
662
|
entry.kind = "https";
|
|
663
|
-
// allow:raw-outbound-http — `client` is the framework httpClient
|
|
663
|
+
// allow:raw-outbound-http-framework-internal — `client` is the framework httpClient
|
|
664
664
|
// (or operator-supplied test mock); SSRF + DNS-pin already
|
|
665
665
|
// applied through the framework wrapper.
|
|
666
666
|
var rv = await client.request({
|
package/lib/pqc-gate.js
CHANGED
|
@@ -232,7 +232,7 @@ function create(opts) {
|
|
|
232
232
|
// each chunk to read the record-length prefix) before deciding
|
|
233
233
|
// whether more data is needed. boundedChunkCollector is append-
|
|
234
234
|
// only with no peek, doesn't fit.
|
|
235
|
-
// allow:handrolled-buffer-collect — see comment above
|
|
235
|
+
// allow:handrolled-buffer-collect-bounded-framing — see comment above
|
|
236
236
|
var buf = Buffer.concat(chunks);
|
|
237
237
|
var recordLen = buf.readUInt16BE(3);
|
|
238
238
|
var neededLen = 5 + recordLen;
|
package/lib/retry.js
CHANGED
|
@@ -284,7 +284,7 @@ function backoffDelay(attempt, opts) {
|
|
|
284
284
|
// 30-50K randomInt/sec under a retry storm without any security
|
|
285
285
|
// payoff. Math.random's PRNG is the right tool for
|
|
286
286
|
// thundering-herd avoidance.
|
|
287
|
-
var jitter = capped * opts.jitterFactor * Math.random(); // allow:math-random-noncrypto — jitter for thundering-herd, not a confidentiality primitive
|
|
287
|
+
var jitter = capped * opts.jitterFactor * Math.random(); // allow:math-random-noncrypto-jitter-sampling — jitter for thundering-herd, not a confidentiality primitive
|
|
288
288
|
return Math.floor(capped - jitter);
|
|
289
289
|
}
|
|
290
290
|
|
package/lib/safe-url.js
CHANGED
|
@@ -444,7 +444,7 @@ function format(url) {
|
|
|
444
444
|
}
|
|
445
445
|
// Constructing URL() is the path that surfaces the IDN-crash on
|
|
446
446
|
// older Node — wrap so the listener never crashes.
|
|
447
|
-
var u = new URL(url); // allow:raw-new-url — safeUrl.format wraps URL ctor for CVE-2026-21712; this IS the safe wrapper.
|
|
447
|
+
var u = new URL(url); // allow:raw-new-url-parse-only — safeUrl.format wraps URL ctor for CVE-2026-21712; this IS the safe wrapper.
|
|
448
448
|
return u.href;
|
|
449
449
|
} catch (e) {
|
|
450
450
|
if (e && e.isSafeUrlError) throw e;
|
package/lib/ssrf-guard.js
CHANGED
|
@@ -754,7 +754,7 @@ function createAllowlist(opts) {
|
|
|
754
754
|
}
|
|
755
755
|
async function assertUrl(url) {
|
|
756
756
|
var parsed;
|
|
757
|
-
try { parsed = new URL(url); } // allow:raw-new-url — local URL parse for hostname extraction
|
|
757
|
+
try { parsed = new URL(url); } // allow:raw-new-url-parse-only — local URL parse for hostname extraction
|
|
758
758
|
catch (_e) {
|
|
759
759
|
throw new SsrfError("invalid URL", "ssrf-guard/bad-url", { url: url });
|
|
760
760
|
}
|
package/lib/vault-aad.js
CHANGED
|
@@ -99,7 +99,7 @@ function _canonicalize(parts) {
|
|
|
99
99
|
valLenBuf.writeUInt32BE(valBuf.length);
|
|
100
100
|
chunks.push(keyLenBuf, keyBuf, valLenBuf, valBuf);
|
|
101
101
|
}
|
|
102
|
-
return Buffer.concat(chunks); // allow:handrolled-buffer-collect — AAD canonicalization, bounded by length-prefixed field shape
|
|
102
|
+
return Buffer.concat(chunks); // allow:handrolled-buffer-collect-bounded-framing — AAD canonicalization, bounded by length-prefixed field shape
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function buildColumnAad(opts) {
|
package/lib/vendor-data.js
CHANGED
|
@@ -176,8 +176,8 @@ function _loadAndVerify(name) {
|
|
|
176
176
|
throw new VendorDataError("vendor-data/module-missing",
|
|
177
177
|
"vendorData: '" + name + "' .data.js module not statically " +
|
|
178
178
|
"require'd by lib/vendor-data.js. Add the literal-string require " +
|
|
179
|
-
"to the _MODULES table at the top of the file — dynamic " + // allow:dynamic-require — diagnostic message text
|
|
180
|
-
"require(variable) breaks SEA / esbuild bundling."); // allow:dynamic-require — diagnostic message text
|
|
179
|
+
"to the _MODULES table at the top of the file — dynamic " + // allow:dynamic-require-operator-module — diagnostic message text
|
|
180
|
+
"require(variable) breaks SEA / esbuild bundling."); // allow:dynamic-require-operator-module — diagnostic message text
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
// Module-shape gate
|
package/lib/websocket.js
CHANGED
|
@@ -460,7 +460,7 @@ function isOriginAllowed(req, origins) {
|
|
|
460
460
|
var host = (req.headers || {}).host;
|
|
461
461
|
if (!host) return false;
|
|
462
462
|
var originHost;
|
|
463
|
-
try { originHost = new URL(origin).host; } // allow:raw-new-url — comparing browser-supplied Origin header against Host; safeUrl.parse adds policy filtering that isn't appropriate for exact host comparison
|
|
463
|
+
try { originHost = new URL(origin).host; } // allow:raw-new-url-parse-only — comparing browser-supplied Origin header against Host; safeUrl.parse adds policy filtering that isn't appropriate for exact host comparison
|
|
464
464
|
catch (_e) { return false; }
|
|
465
465
|
return originHost === host;
|
|
466
466
|
}
|
package/lib/ws-client.js
CHANGED
|
@@ -492,7 +492,7 @@ class WsClient extends EventEmitter {
|
|
|
492
492
|
}
|
|
493
493
|
|
|
494
494
|
_consumeHandshake(chunk) {
|
|
495
|
-
// allow:handrolled-buffer-collect — handshake header capped at 64 KiB below; once handshake parses we switch to FrameParser
|
|
495
|
+
// allow:handrolled-buffer-collect-bounded-framing — handshake header capped at 64 KiB below; once handshake parses we switch to FrameParser
|
|
496
496
|
this._handshakeBuf = Buffer.concat([this._handshakeBuf, chunk]);
|
|
497
497
|
var headerEnd = this._handshakeBuf.indexOf("\r\n\r\n");
|
|
498
498
|
if (headerEnd === -1) {
|
|
@@ -737,7 +737,7 @@ class WsClient extends EventEmitter {
|
|
|
737
737
|
return;
|
|
738
738
|
}
|
|
739
739
|
if (frame.fin) {
|
|
740
|
-
var fullPayload = Buffer.concat(this._fragmentChunks); // allow:handrolled-buffer-collect — bounded by maxMessageBytes below
|
|
740
|
+
var fullPayload = Buffer.concat(this._fragmentChunks); // allow:handrolled-buffer-collect-bounded-framing — bounded by maxMessageBytes below
|
|
741
741
|
if (safeBuffer.byteLengthOf(fullPayload) > this._opts.maxMessageBytes) {
|
|
742
742
|
this._handleSocketError(new WsClientError("ws-client/message-too-big",
|
|
743
743
|
"incoming message exceeds maxMessageBytes (" + this._opts.maxMessageBytes + ")"));
|
|
@@ -964,7 +964,7 @@ class WsClient extends EventEmitter {
|
|
|
964
964
|
this._reconnectAttempt += 1;
|
|
965
965
|
var attempt = Math.min(this._reconnectAttempt, 30); // clamp 2^attempt overflow
|
|
966
966
|
var ceiling = Math.min(rOpts.maxMs, rOpts.baseMs * Math.pow(2, attempt - 1));
|
|
967
|
-
var delay = Math.floor(Math.random() * ceiling); // allow:math-random-noncrypto — backoff jitter, not security
|
|
967
|
+
var delay = Math.floor(Math.random() * ceiling); // allow:math-random-noncrypto-jitter-sampling — backoff jitter, not security
|
|
968
968
|
var self = this;
|
|
969
969
|
this._reconnectTimer = setTimeout(function () {
|
|
970
970
|
self._reconnectTimer = null;
|
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.5",
|
|
5
|
-
"serialNumber": "urn:uuid:
|
|
5
|
+
"serialNumber": "urn:uuid:cfba44f6-db8e-47b3-b1dc-e142692c3a97",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-06-
|
|
8
|
+
"timestamp": "2026-06-26T23:00:05.686Z",
|
|
9
9
|
"lifecycles": [
|
|
10
10
|
{
|
|
11
11
|
"phase": "build"
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"component": {
|
|
22
|
-
"bom-ref": "@blamejs/core@0.15.
|
|
22
|
+
"bom-ref": "@blamejs/core@0.15.33",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "blamejs",
|
|
25
|
-
"version": "0.15.
|
|
25
|
+
"version": "0.15.33",
|
|
26
26
|
"scope": "required",
|
|
27
27
|
"author": "blamejs contributors",
|
|
28
28
|
"description": "The Node framework that owns its stack.",
|
|
29
|
-
"purl": "pkg:npm/%40blamejs/core@0.15.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/core@0.15.33",
|
|
30
30
|
"properties": [],
|
|
31
31
|
"externalReferences": [
|
|
32
32
|
{
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"components": [],
|
|
55
55
|
"dependencies": [
|
|
56
56
|
{
|
|
57
|
-
"ref": "@blamejs/core@0.15.
|
|
57
|
+
"ref": "@blamejs/core@0.15.33",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|