@blamejs/core 0.15.16 → 0.15.17
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/atomic-file.js +32 -9
- package/lib/middleware/api-encrypt.js +105 -40
- package/lib/queue-local.js +123 -46
- package/lib/queue.js +13 -9
- package/lib/self-update-standalone-verifier.js +69 -7
- package/lib/self-update.js +11 -2
- package/lib/vendor/MANIFEST.json +11 -11
- package/lib/vendor/public-suffix-list.dat +6 -2
- package/lib/vendor/public-suffix-list.data.js +689 -688
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/queue.js
CHANGED
|
@@ -938,14 +938,16 @@ function enqueueFlow(spec) {
|
|
|
938
938
|
{ queueName: spec.queueName, flowId: flowId, childCount: spec.children.length },
|
|
939
939
|
async function () {
|
|
940
940
|
var jobs = [];
|
|
941
|
-
// Two-pass insert: first pass enqueues all children
|
|
942
|
-
//
|
|
943
|
-
//
|
|
944
|
-
//
|
|
941
|
+
// Two-pass insert: first pass enqueues all children (so the second pass
|
|
942
|
+
// can resolve dependsOn names → sibling jobIds); a deps-bearing child is
|
|
943
|
+
// PARKED at enqueue time by passing its dependsOn through, so it is never
|
|
944
|
+
// leaseable in the window between the two passes (a concurrent consumer
|
|
945
|
+
// could otherwise lease it before its deps run). The second pass only
|
|
946
|
+
// rewrites the parked child's dependsOn from names to the resolved jobIds.
|
|
945
947
|
var nameToJobId = {};
|
|
946
948
|
for (var p = 0; p < spec.children.length; p++) {
|
|
947
949
|
var ch = spec.children[p];
|
|
948
|
-
|
|
950
|
+
var hasDeps = Array.isArray(ch.dependsOn) && ch.dependsOn.length > 0;
|
|
949
951
|
var enqOpts = {
|
|
950
952
|
backend: flowBackend.name,
|
|
951
953
|
flowId: flowId,
|
|
@@ -954,10 +956,12 @@ function enqueueFlow(spec) {
|
|
|
954
956
|
classification: ch.classification || null,
|
|
955
957
|
traceId: ch.traceId || null,
|
|
956
958
|
maxAttempts: ch.maxAttempts,
|
|
957
|
-
//
|
|
958
|
-
//
|
|
959
|
-
//
|
|
960
|
-
//
|
|
959
|
+
// Park a deps-bearing child immediately (queue-local parks when
|
|
960
|
+
// opts.dependsOn is present); the second pass replaces these dep
|
|
961
|
+
// NAMES with the resolved sibling jobIds, keeping it parked until
|
|
962
|
+
// completion bumps availableAt. Root children (no deps) stay
|
|
963
|
+
// immediately leaseable.
|
|
964
|
+
dependsOn: hasDeps ? ch.dependsOn : undefined,
|
|
961
965
|
};
|
|
962
966
|
var result = await enqueue(spec.queueName, ch.payload, enqOpts);
|
|
963
967
|
nameToJobId[ch.name] = result.jobId;
|
|
@@ -116,6 +116,49 @@ function _detectAlg(pubkeyPem) {
|
|
|
116
116
|
"(need ecdsa-p384, ed25519, or ml-dsa-87)");
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// _looksLikeDerEcdsa — true iff `sig` is a structurally-well-formed ASN.1
|
|
120
|
+
// DER ECDSA signature: SEQUENCE { INTEGER r, INTEGER s }. We dispatch the
|
|
121
|
+
// dsaEncoding by STRUCTURE, never by length: a P-384 DER signature whose r
|
|
122
|
+
// and s both encode short can total exactly 96 bytes — the same length as a
|
|
123
|
+
// raw IEEE-P1363 P-384 signature (48-byte r || 48-byte s) — so a length-only
|
|
124
|
+
// test mis-decodes the valid DER signature as raw and spuriously rejects an
|
|
125
|
+
// otherwise-valid update. This is a shape check only; cryptographic validity
|
|
126
|
+
// is still decided by the single verifier.verify() call below.
|
|
127
|
+
//
|
|
128
|
+
// DER layout: 0x30 <seqLen> 0x02 <rLen> <r...> 0x02 <sLen> <s...>, where each
|
|
129
|
+
// declared length must exactly frame the bytes that follow (definite-form,
|
|
130
|
+
// short or long encoding) and the SEQUENCE body must consume the whole sig.
|
|
131
|
+
function _readDerLen(buf, off) {
|
|
132
|
+
if (off >= buf.length) return null;
|
|
133
|
+
var first = buf[off];
|
|
134
|
+
if (first < 0x80) return { len: first, next: off + 1 }; // short form
|
|
135
|
+
var numBytes = first & 0x7f;
|
|
136
|
+
if (numBytes === 0 || numBytes > 4) return null; // indefinite / oversized: reject
|
|
137
|
+
if (off + 1 + numBytes > buf.length) return null;
|
|
138
|
+
var len = 0;
|
|
139
|
+
for (var i = 0; i < numBytes; i++) len = (len * 256) + buf[off + 1 + i];
|
|
140
|
+
return { len: len, next: off + 1 + numBytes };
|
|
141
|
+
}
|
|
142
|
+
function _readDerInteger(buf, off) {
|
|
143
|
+
if (off >= buf.length || buf[off] !== 0x02) return null; // INTEGER tag
|
|
144
|
+
var l = _readDerLen(buf, off + 1);
|
|
145
|
+
if (l === null || l.len === 0) return null;
|
|
146
|
+
var end = l.next + l.len;
|
|
147
|
+
if (end > buf.length) return null;
|
|
148
|
+
return { next: end };
|
|
149
|
+
}
|
|
150
|
+
function _looksLikeDerEcdsa(sig) {
|
|
151
|
+
if (sig.length < 8 || sig[0] !== 0x30) return false; // SEQUENCE tag
|
|
152
|
+
var seq = _readDerLen(sig, 1);
|
|
153
|
+
if (seq === null) return false;
|
|
154
|
+
if (seq.next + seq.len !== sig.length) return false; // body must frame to end
|
|
155
|
+
var r = _readDerInteger(sig, seq.next);
|
|
156
|
+
if (r === null) return false;
|
|
157
|
+
var s = _readDerInteger(sig, r.next);
|
|
158
|
+
if (s === null) return false;
|
|
159
|
+
return s.next === sig.length; // exactly two INTEGERs, no trailing bytes
|
|
160
|
+
}
|
|
161
|
+
|
|
119
162
|
/**
|
|
120
163
|
* @primitive b.selfUpdate.standaloneVerifier.verify
|
|
121
164
|
* @signature b.selfUpdate.standaloneVerifier.verify(assetPath, signaturePath, pubkeyPem)
|
|
@@ -285,13 +328,32 @@ function verify(assetPath, signaturePath, pubkeyPem) {
|
|
|
285
328
|
|
|
286
329
|
var ok = false;
|
|
287
330
|
if (alg === "ecdsa-p384") {
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
|
|
331
|
+
// Pick the ECDSA signature encoding by STRUCTURE, not by length. A P-384
|
|
332
|
+
// DER signature whose r and s both encode short can total exactly 96
|
|
333
|
+
// bytes — the same length as a raw IEEE-P1363 P-384 signature (48-byte r
|
|
334
|
+
// || 48-byte s) — so a length-only test mis-decodes the valid DER
|
|
335
|
+
// signature as raw and spuriously rejects an otherwise-valid update.
|
|
336
|
+
//
|
|
337
|
+
// A well-formed ASN.1 DER ECDSA signature is a SEQUENCE { INTEGER r,
|
|
338
|
+
// INTEGER s }; raw IEEE-P1363 is exactly 2*coordLen bytes (coordLen =
|
|
339
|
+
// 48 for the P-384 field). If it parses as DER, treat as DER; else if it
|
|
340
|
+
// is exactly 2*coordLen, treat as raw; else fail closed. We call
|
|
341
|
+
// verifier.verify() ONCE — a second call after a failed verify returns
|
|
342
|
+
// stale state and can silently pass tampered assets.
|
|
343
|
+
var coordLen = 48; // P-384 field element width in bytes; protocol constant, not a byte-size cap
|
|
344
|
+
var dsaEncoding;
|
|
345
|
+
if (_looksLikeDerEcdsa(signature)) {
|
|
346
|
+
dsaEncoding = "der";
|
|
347
|
+
} else if (signature.length === coordLen * 2) {
|
|
348
|
+
dsaEncoding = "ieee-p1363";
|
|
349
|
+
} else {
|
|
350
|
+
// assetFd was already closed by the read loop's `finally`; this is a
|
|
351
|
+
// pure fail-closed refusal, same as the `if (!ok)` path below.
|
|
352
|
+
throw new Error("standalone-verifier.verify: ecdsa-p384 signature is neither a " +
|
|
353
|
+
"well-formed DER SEQUENCE nor a raw " + (coordLen * 2) +
|
|
354
|
+
"-byte IEEE-P1363 pair (length " + signature.length +
|
|
355
|
+
") — refusing to guess the encoding");
|
|
356
|
+
}
|
|
295
357
|
ok = verifier.verify({ key: key, dsaEncoding: dsaEncoding }, signature);
|
|
296
358
|
} else if (alg === "ed25519") {
|
|
297
359
|
// fullBuf may be shorter than allocated (sparse files / size-races);
|
package/lib/self-update.js
CHANGED
|
@@ -297,6 +297,13 @@ function _matchAsset(name, pattern, fallback) {
|
|
|
297
297
|
* with conservative fallbacks. Throws SelfUpdateError on a non-2xx
|
|
298
298
|
* upstream, malformed JSON, or unexpected shape.
|
|
299
299
|
*
|
|
300
|
+
* Each matched asset / signature is reported as
|
|
301
|
+
* `{ name, url, size, digest }`. `digest` carries the release API's
|
|
302
|
+
* published `assets[].digest` (e.g. `"sha256:<hex>"`) verbatim when the
|
|
303
|
+
* upstream supplies it, or `null` when absent — a consumer can use it
|
|
304
|
+
* for a defense-in-depth in-flight integrity check of the downloaded
|
|
305
|
+
* bytes alongside the detached-signature verify.
|
|
306
|
+
*
|
|
300
307
|
* @opts
|
|
301
308
|
* releasesUrl: string, // required — feed URL
|
|
302
309
|
* currentVersion: string, // required — e.g. "0.8.43" or "v0.8.43"
|
|
@@ -446,11 +453,13 @@ async function poll(opts) {
|
|
|
446
453
|
var a = assets[i] || {};
|
|
447
454
|
if (typeof a.name !== "string" || typeof a.browser_download_url !== "string") continue;
|
|
448
455
|
if (signatureMatch === null && _matchAsset(a.name, opts.signaturePattern, /\.sig$|\.asc$|\.sig\.bin$/i)) {
|
|
449
|
-
signatureMatch = { name: a.name, url: a.browser_download_url, size: a.size || null
|
|
456
|
+
signatureMatch = { name: a.name, url: a.browser_download_url, size: a.size || null,
|
|
457
|
+
digest: typeof a.digest === "string" ? a.digest : null };
|
|
450
458
|
continue;
|
|
451
459
|
}
|
|
452
460
|
if (assetMatch === null && _matchAsset(a.name, opts.assetPattern, /\.(tar\.gz|tgz|zip|node|exe|bin)$/i)) {
|
|
453
|
-
assetMatch = { name: a.name, url: a.browser_download_url, size: a.size || null
|
|
461
|
+
assetMatch = { name: a.name, url: a.browser_download_url, size: a.size || null,
|
|
462
|
+
digest: typeof a.digest === "string" ? a.digest : null };
|
|
454
463
|
}
|
|
455
464
|
}
|
|
456
465
|
|
package/lib/vendor/MANIFEST.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"hashes": {
|
|
19
19
|
"server": "sha256:5d539dfc9ef47121d4c09bd7256d76448a1f5ac47ee09ac44c78ff6a062af9ab"
|
|
20
20
|
},
|
|
21
|
-
"refreshedAt": "2026-06-
|
|
21
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
22
22
|
},
|
|
23
23
|
"@noble/curves": {
|
|
24
24
|
"version": "2.2.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"hashes": {
|
|
41
41
|
"server": "sha256:ebf254d5eb56aef8705a1c4af9603f47987b4870a9bb5e657e06907b701e2731"
|
|
42
42
|
},
|
|
43
|
-
"refreshedAt": "2026-06-
|
|
43
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
44
44
|
},
|
|
45
45
|
"@noble/post-quantum": {
|
|
46
46
|
"version": "0.6.1",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"hashes": {
|
|
72
72
|
"server": "sha256:f9190309daadca4c2e2cc2b76beaa6b96e463429cc3c390bd9f0ceaf7b588c68"
|
|
73
73
|
},
|
|
74
|
-
"refreshedAt": "2026-06-
|
|
74
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
75
75
|
},
|
|
76
76
|
"@simplewebauthn/server": {
|
|
77
77
|
"version": "13.3.1",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"hashes": {
|
|
95
95
|
"server": "sha256:f359a782ac57e3ff56ac71083d17f5c082f88ab49d645fc2bede398b47adebdb"
|
|
96
96
|
},
|
|
97
|
-
"refreshedAt": "2026-06-
|
|
97
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
98
98
|
},
|
|
99
99
|
"SecLists-common-passwords-top-10000": {
|
|
100
100
|
"version": "10k-most-common (master)",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
},
|
|
115
115
|
"runtime_artifact": "lib/vendor/common-passwords-top-10000.data.js",
|
|
116
116
|
"integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
|
|
117
|
-
"refreshedAt": "2026-06-
|
|
117
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
118
118
|
},
|
|
119
119
|
"bimi-trust-anchors": {
|
|
120
120
|
"version": "operator-managed",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
},
|
|
140
140
|
"runtime_artifact": "lib/vendor/bimi-trust-anchors.data.js",
|
|
141
141
|
"integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
|
|
142
|
-
"refreshedAt": "2026-06-
|
|
142
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
143
143
|
},
|
|
144
144
|
"publicsuffix-list": {
|
|
145
145
|
"version": "master",
|
|
@@ -152,14 +152,14 @@
|
|
|
152
152
|
"data_js": "lib/vendor/public-suffix-list.data.js"
|
|
153
153
|
},
|
|
154
154
|
"bundler": "curl https://publicsuffix.org/list/public_suffix_list.dat",
|
|
155
|
-
"bundledAt": "2026-
|
|
155
|
+
"bundledAt": "2026-06-22T00:00:00Z",
|
|
156
156
|
"hashes": {
|
|
157
|
-
"server": "sha256:
|
|
158
|
-
"data_js": "sha256:
|
|
157
|
+
"server": "sha256:0adddeb62057d8d40799dffb29fe14f65dd009259afe02eb2f0b4602b791aae6",
|
|
158
|
+
"data_js": "sha256:82af512cacf0fd2c60925e63f877b69477b1b2f7bb5af698fd862af61369902e"
|
|
159
159
|
},
|
|
160
160
|
"runtime_artifact": "lib/vendor/public-suffix-list.data.js",
|
|
161
161
|
"integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
|
|
162
|
-
"refreshedAt": "2026-06-
|
|
162
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
163
163
|
},
|
|
164
164
|
"peculiar-pki": {
|
|
165
165
|
"version": "2.0.0+pkijs-3.4.0",
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
"hashes": {
|
|
191
191
|
"server": "sha256:9bbc191afaaa2b1e5757f00480457c08134cdc2c55d541df18d9155bba9cbf77"
|
|
192
192
|
},
|
|
193
|
-
"refreshedAt": "2026-06-
|
|
193
|
+
"refreshedAt": "2026-06-22T16:29:46.590Z"
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat,
|
|
6
6
|
// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported.
|
|
7
7
|
|
|
8
|
-
// VERSION: 2026-06-
|
|
9
|
-
// COMMIT:
|
|
8
|
+
// VERSION: 2026-06-22_11-46-12_UTC
|
|
9
|
+
// COMMIT: 27a7b5d881b91def306422e6cc243f05c49f3a58
|
|
10
10
|
|
|
11
11
|
// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/.
|
|
12
12
|
|
|
@@ -14721,6 +14721,10 @@ mittwaldserver.info
|
|
|
14721
14721
|
typo3server.info
|
|
14722
14722
|
project.space
|
|
14723
14723
|
|
|
14724
|
+
// MKM : https://mkm.fan/
|
|
14725
|
+
// Submitted by Kashi Ahmer <admin@mkm.fan>
|
|
14726
|
+
mkm.fan
|
|
14727
|
+
|
|
14724
14728
|
// Mocha : https://getmocha.com
|
|
14725
14729
|
// Submitted by Ben Reinhart <security@getmocha.com>
|
|
14726
14730
|
mocha.app
|