@blamejs/core 0.11.3 → 0.11.4
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/lib/audit.js +151 -1
- package/lib/websocket.js +15 -3
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.11.x
|
|
10
10
|
|
|
11
|
+
- v0.11.4 (2026-05-19) — **`b.audit.useStore({ record })` shadow store + WebSocket permessage-deflate bomb fix + 5 new codebase-patterns detectors + shape-matcher substrate.** **`b.audit.useStore({ record })`** registers an operator-supplied shadow store that receives a copy of every audit chain append AFTER the framework's tamper-evident chain commits. The operator's `record(row)` async function receives the fully-formed row — `{ _id, recordedAt, monotonicCounter, prevHash, rowHash, action, outcome, actorUserId, ..., metadata }` — so external destinations (AWS QLDB / Azure Confidential Ledger / Google Cloud Audit Logs / in-house WORM appliances / SIEM forwarders) see identical hashes for cross-store reconciliation. Shadow failures are drop-silent per [CLAUDE.md rule §5](https://github.com/blamejs/blamejs/blob/main/CLAUDE.md) — the framework chain is authoritative and already committed; an unreachable shadow surfaces via `b.observability` as the `audit.shadow_failed` event but never crashes the request path. Composes with HIPAA §164.312(b) / PCI-DSS Req 10.5.3 (separation-of-duties retention) / SOX §404 / SEC 17a-4 WORM postures. Pass `null` or `{ record: null }` to unregister. **WebSocket permessage-deflate bomb fix:** `lib/websocket.js` `_inflateMessage` previously called `zlib.inflateRawSync` without `maxOutputLength` — a malicious peer could ship a small compressed frame that exploded into gigabytes BEFORE the framework's post-decompression `maxMessageBytes` check ran. The inflate now passes `maxOutputLength: this.maxMessageBytes` so zlib refuses mid-decompress; same CVE-2024-zlib / CVE-2025-0725 amplification class the `gunzip-without-output-size-cap` detector defends elsewhere. **New codebase-patterns detectors:** (1) `test-promise-settimeout-sleep` (scans the `test/` tree — first detector under the new test-scope walker — for the `await new Promise(r => setTimeout(r, N))` shape forbidden by [CLAUDE.md §11b](https://github.com/blamejs/blamejs/blob/main/CLAUDE.md), with the migration backlog pre-allowlisted as a release-gate countdown); (2) `inflate-unzip-without-output-size-cap` (extends the v0.10.15 gunzip-cap detector to `zlib.inflateSync` / `inflateRawSync` / `unzipSync` / `createInflate` family — RFC 1951 deflate is the same bomb class); (3) `map-get-falsy-then-set-pre-node-26` (companion to `map-has-then-set-pre-node-26` — catches the `!M.get(k)` / `M.get(k) === undefined|null` semantically-identical variants); (4) `fs-existssync-then-read-toctou` (CodeQL `js/file-system-race` class — `fs.existsSync(p) + fs.readFile(p)` against the same path is symlink-swap-vulnerable; the canonical defense is `lib/atomic-file.js`'s open-by-fd-first pattern); (5) `buffer-from-string-on-auth-path` (flags `Buffer.from(String(x))` in `lib/` — auth-bearing sites become `b.safeBytes` migration targets in the next release). **Shape-matcher substrate** lands at `test/helpers/_shape-match.js` (test-only, never ships — `test/` is absent from package.json `files:` allowlist): token-aware traversal that tracks paren / brace / bracket depth + string / template-literal / regex / comment state, exposing `findCalls(source, calleeRegex)` / `findEnclosingTry(source, pos)` / `aliasesOf(source, chainRegex)`. Future releases convert the highest-bypass-risk regex-only detectors to AST-aware variants using this substrate, closing the class of regex-bypass via variable renaming / parens / line splits that surface-pattern detectors miss. **References:** [RFC 7692 §7.2.2 WebSocket permessage-deflate](https://www.rfc-editor.org/rfc/rfc7692#section-7.2.2) · [HIPAA §164.312(b) Audit Controls](https://www.law.cornell.edu/cfr/text/45/164.312) · [PCI-DSS v4.0 Req 10](https://www.pcisecuritystandards.org/) · [SEC 17a-4 WORM](https://www.sec.gov/files/rules/final/34-44238.pdf) · [SOX §404](https://www.sec.gov/about/laws/soa2002.pdf) · [CVE-2024-zlib decompression amplification](https://nvd.nist.gov/) · [CVE-2025-0725](https://nvd.nist.gov/vuln/detail/CVE-2025-0725) · [CodeQL js/file-system-race](https://codeql.github.com/codeql-query-help/javascript/js-file-system-race/).
|
|
12
|
+
|
|
11
13
|
- v0.11.3 (2026-05-19) — **SPF `a` and `mx` mechanism dispatch + smaller deferral-condition cleanups.** `b.mail.spf.verify` now evaluates the `a` and `mx` mechanisms per [RFC 7208 §5.3 + §5.4](https://www.rfc-editor.org/rfc/rfc7208), including the dual-cidr-length syntax (`a:foo.example/24//64`, `mx//64`). Senders publishing `v=spf1 mx -all` or `v=spf1 a -all` previously permerrored against this framework even though those are the second-most-common SPF mechanisms in fielded policies; verification now resolves the operator-supplied A / AAAA / MX records (via the existing `dnsLookup` callback contract — which is now honored for every record type, not only TXT) and matches the connecting IP under the parsed cidr. MX expansion is capped at the RFC §4.6.4 limit of 10 hosts (over-limit = permerror); each MX-host A/AAAA expansion counts toward the 10-lookup global ceiling and the 2-lookup void-lookup sub-limit. Empty digit segments in the dual-cidr-length grammar (`a/`, `a//`, `mx/`, `mx//`, `a/24//`) permerror with an explanatory message — RFC §5.3/§5.4 grammar requires `1*DIGIT` after each slash, and accepting empty would over-authorize senders publishing `v=spf1 a/ -all` (would match every IP in the /32 of every A record). The `exists` (RFC §5.7) and `ptr` (RFC §5.5) mechanisms remain deferred — `exists` needs macro-string expansion (RFC §7) to be usable in fielded policies, `ptr` is "strongly discouraged" by the RFC and rarely seen — and each now permerrors with an explanatory message naming the RFC section and a practical operator-side mitigation. `b.mail.crypto.smime` `@card` and the v1-only-emits-metadata comment in `lib/mail-crypto-smime.js` are corrected to reflect that sign + verify shipped in v0.10.16 on the `b.cms` substrate (EFAIL-class encrypt/decrypt remains the only deferred slice). `b.acme.create.revokeCert({ useCertKey: true })` and the `BAD UID <subverb>` IMAP listener response now carry explicit re-open conditions + named operator escape hatches alongside the deferral. **New codebase-patterns detector `slice1-optional-parseint-silent-default`** flags the class — any `.slice(1)` followed by an `if (X.length > 0)` guard around `parseInt(X, 10)` MUST sit in a file that also carries an explicit empty-segment refusal phrasing, so future cidr-length / prefix-length / port-range parsers inherit the discipline automatically. **References:** [RFC 7208 §5.3 a mechanism](https://www.rfc-editor.org/rfc/rfc7208#section-5.3) · [RFC 7208 §5.4 mx mechanism](https://www.rfc-editor.org/rfc/rfc7208#section-5.4) · [RFC 7208 §4.6.4 DNS-lookup limits](https://www.rfc-editor.org/rfc/rfc7208#section-4.6.4) · [RFC 8551 S/MIME 4.0](https://www.rfc-editor.org/rfc/rfc8551.html) · [RFC 9051 IMAP4rev2 §6.4.9 UID](https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9).
|
|
12
14
|
|
|
13
15
|
- v0.11.2 (2026-05-19) — **Node 26 floor-bump preparation.** Today's `engines.node` floor is `>=24.14.1` and the framework runs cleanly on Node 26 (which satisfies the floor). This release ships the **prep** scaffolding so the future floor-bump slice (when Node 26 promotes to Active LTS and `>=26.x` becomes the floor) is mechanical. **`b.backup.diskStorage(opts)`** is the new canonical name for the local-filesystem backup storage backend; `b.backup.localStorage(opts)` continues to work and emits a one-time deprecation warning via `b.deprecate.alias`, with removal scheduled for the next major. The rename avoids the Node 26 platform-level `localStorage` global naming collision; the deprecation path follows the framework's stable upgrade policy (one minor with deprecation warnings before removal). **New codebase-patterns detector `map-get-or-insert-pre-node-26`** flags the `if (!m.has(k)) m.set(k, factory()); m.get(k)` shape that Node 26's `Map.prototype.getOrInsertComputed(key, factory)` replaces in a single call. The detector lands as an allowlist marker — every existing call site in `lib/` is allowlisted with the spec file as the migration target; new code post-this-patch trips the gate. When the floor bumps the allowlist is walked + the detector flips to enforce. **`test/integration/pqc-pkcs8-forward-compat.test.js`** captures the ML-KEM-1024 / ML-DSA-65 / ML-DSA-87 / SLH-DSA-SHAKE-256f / Ed25519 PKCS8 export-byte shape on the current Node, asserts the sign+verify / encap+decap roundtrip via a re-imported KeyObject, and embeds a Node-26-shape fixture that re-imports every run — so the forward-compat contract is testable today and the reverse-direction (Node-26-exported → Node-24-imported) test follows the floor-bump. **SECURITY.md gains a "Node 26 compatibility" section** documenting the `localStorage` global naming collision (bare references in operator handler code now resolve to a Node global rather than throwing `ReferenceError`) and the ML-KEM / ML-DSA seed-only PKCS8 export shape (Node-24-sealed material re-imports cleanly on Node 26; new material from Node 26 is seed-only — parallel Node 24 readers of the same sealed disk need a one-time migration when the writer moves). README "Requirements" line gains the matching Node 26 note. **References:** [Node.js v26 release notes](https://nodejs.org/en/blog/release/v26.0.0) · [TC39 Map.getOrInsertComputed](https://github.com/tc39/proposal-upsert) · [RFC 8032 §5.1 Ed25519 context parameter](https://www.rfc-editor.org/rfc/rfc8032.html#section-5.1).
|
package/lib/audit.js
CHANGED
|
@@ -68,6 +68,33 @@ var { AuditSegregationError, ClusterError } = require("./framework-error");
|
|
|
68
68
|
|
|
69
69
|
var log = boot("audit");
|
|
70
70
|
|
|
71
|
+
// External shadow-store callbacks are bounded by the same hot-path
|
|
72
|
+
// timeout the framework's own SQL paths use. A stalled operator
|
|
73
|
+
// network call that neither resolves nor rejects MUST NOT block the
|
|
74
|
+
// audit critical path — b.audit.record() must return, emit/safeEmit
|
|
75
|
+
// drains must not stall behind it. On timeout the shadow record is
|
|
76
|
+
// dropped (audit.shadow_timeout observability event) and the
|
|
77
|
+
// framework chain row remains committed. CLAUDE.md rule §5 drop-
|
|
78
|
+
// silent posture for hot-path observability sinks.
|
|
79
|
+
var EXTERNAL_STORE_TIMEOUT_MS = C.TIME.seconds(30);
|
|
80
|
+
|
|
81
|
+
// External shadow store registered via `b.audit.useStore({ record })`.
|
|
82
|
+
// When set, every successful framework chain.append also fires
|
|
83
|
+
// `_externalStore.record(rowResult)` so operators can replicate audit
|
|
84
|
+
// records to an immutable external destination (AWS QLDB, Azure
|
|
85
|
+
// Confidential Ledger, Google Cloud Audit Logs, an in-house WORM
|
|
86
|
+
// appliance, a SIEM, etc.) WITHOUT giving up the framework's tamper-
|
|
87
|
+
// evident chain integrity. The framework's chain remains authoritative;
|
|
88
|
+
// the operator's record receives the fully-formed row (logical fields +
|
|
89
|
+
// `_id` + `recordedAt` + `monotonicCounter` + `prevHash` + `rowHash`).
|
|
90
|
+
//
|
|
91
|
+
// Shadow failures are drop-silent (rule §5 — hot-path observability
|
|
92
|
+
// sinks must not crash the path that emitted them). An audit-shadow
|
|
93
|
+
// failure surfaces via `b.observability` as `audit.shadow_failed`; the
|
|
94
|
+
// framework chain row still committed and downstream verifyChain still
|
|
95
|
+
// works against the framework store.
|
|
96
|
+
var _externalStore = null;
|
|
97
|
+
|
|
71
98
|
// Per-operation timeout for framework-state SQL. A misbehaving
|
|
72
99
|
// external-db driver hanging on a query shouldn't hang audit forever.
|
|
73
100
|
// 30s is generous for genuinely slow networks while still bounding
|
|
@@ -451,11 +478,132 @@ async function record(event) {
|
|
|
451
478
|
metadata: event.metadata ? JSON.stringify(event.metadata) : null,
|
|
452
479
|
requestId: event.requestId || null,
|
|
453
480
|
};
|
|
454
|
-
|
|
481
|
+
var appended = await _chainWriter.append(logical);
|
|
482
|
+
// Operator-registered shadow store: replicate the fully-formed
|
|
483
|
+
// row to an immutable external destination. Drop-silent on
|
|
484
|
+
// failure (rule §5) — the framework chain is authoritative and
|
|
485
|
+
// already committed; the shadow is a best-effort archival.
|
|
486
|
+
// The operator's record receives the SAME object the framework
|
|
487
|
+
// returns to its caller, so external consumers see identical
|
|
488
|
+
// hashes / counters / ids for cross-store reconciliation.
|
|
489
|
+
if (_externalStore && typeof _externalStore.record === "function") {
|
|
490
|
+
// Bound the operator-supplied callback so a stalled network
|
|
491
|
+
// call can't hang the audit critical path. Timeout, throw,
|
|
492
|
+
// and resolve paths all converge on the framework chain row
|
|
493
|
+
// staying durable — the shadow is best-effort archival.
|
|
494
|
+
try {
|
|
495
|
+
await safeAsync.withTimeout(
|
|
496
|
+
Promise.resolve().then(function () { return _externalStore.record(appended); }),
|
|
497
|
+
EXTERNAL_STORE_TIMEOUT_MS,
|
|
498
|
+
{ name: "audit.shadowRecord" }
|
|
499
|
+
);
|
|
500
|
+
} catch (e) {
|
|
501
|
+
var isTimeout = e && (e.code === "ETIMEDOUT" || /timeout/i.test(e.message || ""));
|
|
502
|
+
try {
|
|
503
|
+
observability.event(isTimeout ? "audit.shadow_timeout" : "audit.shadow_failed", {
|
|
504
|
+
action: appended.action,
|
|
505
|
+
monotonicCounter: appended.monotonicCounter,
|
|
506
|
+
error: (e && e.message) || String(e),
|
|
507
|
+
timeoutMs: isTimeout ? EXTERNAL_STORE_TIMEOUT_MS : undefined,
|
|
508
|
+
});
|
|
509
|
+
} catch (_obs) { /* drop-silent — observability is itself hot-path */ }
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return appended;
|
|
455
513
|
}
|
|
456
514
|
);
|
|
457
515
|
}
|
|
458
516
|
|
|
517
|
+
/**
|
|
518
|
+
* @primitive b.audit.useStore
|
|
519
|
+
* @signature b.audit.useStore({ record })
|
|
520
|
+
* @since 0.11.4
|
|
521
|
+
* @status stable
|
|
522
|
+
* @compliance hipaa, pci-dss, gdpr, soc2, sox-404
|
|
523
|
+
* @related b.audit.record, b.audit.safeEmit
|
|
524
|
+
*
|
|
525
|
+
* Register an operator-supplied shadow store for every audit chain
|
|
526
|
+
* append. The framework's tamper-evident chain remains authoritative
|
|
527
|
+
* (HIPAA §164.312(b) / PCI-DSS Req 10 / SOX-404 / ISO 27001 A.12.4.1
|
|
528
|
+
* posture preserved); the operator's `record(row)` async function is
|
|
529
|
+
* called AFTER each successful framework chain.append with the FULL
|
|
530
|
+
* appended row — `{ _id, recordedAt, monotonicCounter, prevHash,
|
|
531
|
+
* rowHash, action, outcome, actorUserId, ..., metadata }` — so
|
|
532
|
+
* external consumers see identical hashes for cross-store
|
|
533
|
+
* reconciliation.
|
|
534
|
+
*
|
|
535
|
+
* Typical use: replicate audit records to an immutable external
|
|
536
|
+
* destination (AWS QLDB / Azure Confidential Ledger / Google Cloud
|
|
537
|
+
* Audit Logs / an in-house WORM appliance / a SIEM forwarder).
|
|
538
|
+
* Operators in regulated industries often need their audit trail in
|
|
539
|
+
* a destination outside the application's own database for
|
|
540
|
+
* separation-of-duties (PCI-DSS Req 10.5.3) or independent retention
|
|
541
|
+
* (HIPAA §164.312(b) / SEC 17a-4 WORM).
|
|
542
|
+
*
|
|
543
|
+
* Failure posture: if the operator's `record` throws / rejects /
|
|
544
|
+
* times out (30s hard cap — a stalled network call MUST NOT block
|
|
545
|
+
* the audit critical path), the shadow failure is surfaced via
|
|
546
|
+
* `b.observability` as either `audit.shadow_failed` (throw/reject)
|
|
547
|
+
* or `audit.shadow_timeout` (cap exceeded) with `{ action,
|
|
548
|
+
* monotonicCounter, error, timeoutMs }` metadata, and the framework
|
|
549
|
+
* chain append still succeeds (the row is durable in the framework's
|
|
550
|
+
* own table; the shadow is a best-effort archival). This is the
|
|
551
|
+
* rule §5 drop-silent posture for hot-path observability sinks — an
|
|
552
|
+
* unreachable / hanging shadow MUST NOT crash or stall the request
|
|
553
|
+
* path that triggered the audit attempt.
|
|
554
|
+
*
|
|
555
|
+
* Call this once at boot, BEFORE the first `b.audit.record` /
|
|
556
|
+
* `b.audit.emit` / `b.audit.safeEmit`. Switching stores on a running
|
|
557
|
+
* app strands every prior audit row in the previous shadow store —
|
|
558
|
+
* the framework chain has them, but the new shadow doesn't unless
|
|
559
|
+
* the operator backfills.
|
|
560
|
+
*
|
|
561
|
+
* Pass `null` (or `{ record: null }`) to unregister and revert to
|
|
562
|
+
* chain-only mode.
|
|
563
|
+
*
|
|
564
|
+
* @opts
|
|
565
|
+
* record: async function (row), // operator's persistence callback
|
|
566
|
+
*
|
|
567
|
+
* @example
|
|
568
|
+
* var b = require("@blamejs/core");
|
|
569
|
+
* await b.vault.init({ dataDir: "/var/lib/blamejs", mode: "plaintext" });
|
|
570
|
+
* await b.db.init({ dataDir: "/var/lib/blamejs" });
|
|
571
|
+
* b.audit.useStore({
|
|
572
|
+
* record: async function (row) {
|
|
573
|
+
* // Replicate to AWS QLDB / Azure Confidential Ledger / etc.
|
|
574
|
+
* await externalLedger.append({
|
|
575
|
+
* id: row._id,
|
|
576
|
+
* recordedAt: row.recordedAt,
|
|
577
|
+
* monotonicCounter: row.monotonicCounter,
|
|
578
|
+
* prevHash: row.prevHash,
|
|
579
|
+
* rowHash: row.rowHash,
|
|
580
|
+
* action: row.action,
|
|
581
|
+
* outcome: row.outcome,
|
|
582
|
+
* metadata: row.metadata,
|
|
583
|
+
* });
|
|
584
|
+
* },
|
|
585
|
+
* });
|
|
586
|
+
* // Every b.audit.* append now also lands in externalLedger.
|
|
587
|
+
*/
|
|
588
|
+
function useStore(store) {
|
|
589
|
+
if (store === null || store === undefined) {
|
|
590
|
+
_externalStore = null;
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
if (typeof store !== "object") {
|
|
594
|
+
throw new Error("audit.useStore: store must be an object with a record(row) function, or null to unregister");
|
|
595
|
+
}
|
|
596
|
+
// `{ record: null }` unregisters explicitly (mirrors the null arg path).
|
|
597
|
+
if (store.record === null || store.record === undefined) {
|
|
598
|
+
_externalStore = null;
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
if (typeof store.record !== "function") {
|
|
602
|
+
throw new Error("audit.useStore: store.record must be an async function (row) => void");
|
|
603
|
+
}
|
|
604
|
+
_externalStore = store;
|
|
605
|
+
}
|
|
606
|
+
|
|
459
607
|
// ---- Query ----
|
|
460
608
|
//
|
|
461
609
|
// Plain-field criteria translate into derived-hash equality where the column
|
|
@@ -911,6 +1059,7 @@ async function verify(opts) {
|
|
|
911
1059
|
|
|
912
1060
|
function _resetForTest() {
|
|
913
1061
|
registeredNamespaces = new Set(FRAMEWORK_NAMESPACES);
|
|
1062
|
+
_externalStore = null;
|
|
914
1063
|
db.reset();
|
|
915
1064
|
_chainWriter._resetForTest();
|
|
916
1065
|
// Drop pending buffered emits and cancel the age-flush timer on the
|
|
@@ -1500,6 +1649,7 @@ function activePosture() { return _activePosture; }
|
|
|
1500
1649
|
module.exports = {
|
|
1501
1650
|
registerNamespace: registerNamespace,
|
|
1502
1651
|
record: record,
|
|
1652
|
+
useStore: useStore,
|
|
1503
1653
|
emit: emit,
|
|
1504
1654
|
safeEmit: safeEmit,
|
|
1505
1655
|
applyPosture: applyPosture,
|
package/lib/websocket.js
CHANGED
|
@@ -603,10 +603,17 @@ function _deflateMessage(payload, windowBits) {
|
|
|
603
603
|
return raw;
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
function _inflateMessage(payload, windowBits) {
|
|
606
|
+
function _inflateMessage(payload, windowBits, maxOutputBytes) {
|
|
607
607
|
// Per RFC 7692 §7.2.2, append the 4-byte trailer before inflating.
|
|
608
|
+
// `maxOutputBytes` MUST be bounded by the caller's per-message cap so
|
|
609
|
+
// a malicious peer can't ship a small deflated frame that explodes
|
|
610
|
+
// into gigabytes before the framework's downstream size-check sees
|
|
611
|
+
// the inflated bytes. CVE-2024-zlib + CVE-2025-0725 bomb class.
|
|
608
612
|
var withTrailer = Buffer.concat([payload, DEFLATE_TRAILING]);
|
|
609
|
-
return zlib.inflateRawSync(withTrailer, {
|
|
613
|
+
return zlib.inflateRawSync(withTrailer, {
|
|
614
|
+
windowBits: windowBits,
|
|
615
|
+
maxOutputLength: maxOutputBytes,
|
|
616
|
+
});
|
|
610
617
|
}
|
|
611
618
|
|
|
612
619
|
// ---- Frame parser ----
|
|
@@ -1065,8 +1072,13 @@ class WebSocketConnection extends EventEmitter {
|
|
|
1065
1072
|
// CLOSE_INVALID_PAYLOAD per §5.6 / §6 of RFC 6455.
|
|
1066
1073
|
if (wasCompressed) {
|
|
1067
1074
|
try {
|
|
1068
|
-
data = _inflateMessage(data, this._permessageDeflate.clientMaxWindowBits
|
|
1075
|
+
data = _inflateMessage(data, this._permessageDeflate.clientMaxWindowBits,
|
|
1076
|
+
this.maxMessageBytes);
|
|
1069
1077
|
} catch (e) {
|
|
1078
|
+
// RFC 6455 §7.4.1 / §5.6 — protocol-level decode failure
|
|
1079
|
+
// (including bomb-cap overrun via maxOutputLength) returns
|
|
1080
|
+
// CLOSE_INVALID_PAYLOAD. The over-cap case never allocates the
|
|
1081
|
+
// exploded bytes — zlib's maxOutputLength refuses mid-inflate.
|
|
1070
1082
|
return this._abort(CLOSE_INVALID_PAYLOAD,
|
|
1071
1083
|
"permessage-deflate inflate failed: " + ((e && e.message) || String(e)));
|
|
1072
1084
|
}
|
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:3a3e9e86-231c-4b20-b40a-2d58ef84de56",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-05-
|
|
8
|
+
"timestamp": "2026-05-19T19:19:53.073Z",
|
|
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.11.
|
|
22
|
+
"bom-ref": "@blamejs/core@0.11.4",
|
|
23
23
|
"type": "library",
|
|
24
24
|
"name": "blamejs",
|
|
25
|
-
"version": "0.11.
|
|
25
|
+
"version": "0.11.4",
|
|
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.11.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/core@0.11.4",
|
|
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.11.
|
|
57
|
+
"ref": "@blamejs/core@0.11.4",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|