@blamejs/blamejs-shop 0.5.19 → 0.5.20
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/admin.js +35 -40
- package/lib/asset-manifest.json +1 -1
- package/lib/externaldb-d1.js +31 -21
- package/lib/payment.js +103 -58
- package/lib/referrals.js +10 -6
- package/lib/security-middleware.js +39 -12
- package/lib/site-redirects.js +44 -121
- package/lib/storefront.js +19 -21
- package/lib/vendor/MANIFEST.json +107 -97
- package/lib/vendor/blamejs/CHANGELOG.md +180 -0
- package/lib/vendor/blamejs/NOTICE +14 -10
- package/lib/vendor/blamejs/README.md +17 -5
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/acme.js +9 -9
- package/lib/vendor/blamejs/lib/api-snapshot.js +35 -16
- package/lib/vendor/blamejs/lib/app-shutdown.js +1 -1
- package/lib/vendor/blamejs/lib/archive-adapters.js +1 -1
- package/lib/vendor/blamejs/lib/archive.js +13 -24
- package/lib/vendor/blamejs/lib/auth/access-lock.js +2 -1
- package/lib/vendor/blamejs/lib/auth/bot-challenge.js +3 -6
- package/lib/vendor/blamejs/lib/auth/ciba.js +32 -3
- package/lib/vendor/blamejs/lib/auth/oauth.js +65 -8
- package/lib/vendor/blamejs/lib/auth/password.js +1 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +21 -3
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +3 -3
- package/lib/vendor/blamejs/lib/backup/index.js +5 -5
- package/lib/vendor/blamejs/lib/case-fold-classes.js +491 -0
- package/lib/vendor/blamejs/lib/codepoint-class.js +131 -0
- package/lib/vendor/blamejs/lib/constants.js +79 -0
- package/lib/vendor/blamejs/lib/db-declare-view.js +8 -2
- package/lib/vendor/blamejs/lib/error-page.js +20 -1
- package/lib/vendor/blamejs/lib/external-db.js +5 -1
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +24 -6
- package/lib/vendor/blamejs/lib/flag.js +28 -2
- package/lib/vendor/blamejs/lib/framework-schema.js +14 -3
- package/lib/vendor/blamejs/lib/guard-regex.js +2345 -89
- package/lib/vendor/blamejs/lib/http-client.js +217 -40
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +26 -26
- package/lib/vendor/blamejs/lib/mail-deploy.js +10 -10
- package/lib/vendor/blamejs/lib/mail-scan.js +3 -0
- package/lib/vendor/blamejs/lib/mail-store.js +7 -1
- package/lib/vendor/blamejs/lib/mail.js +5 -1
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/compression.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/cors.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +5 -5
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/dpop.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/flag-context.js +17 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +10 -8
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-aal.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-auth.js +4 -3
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +4 -3
- package/lib/vendor/blamejs/lib/middleware/require-content-type.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-methods.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/require-mtls.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -1
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +1 -1
- package/lib/vendor/blamejs/lib/network-dns.js +3 -3
- package/lib/vendor/blamejs/lib/network-nts.js +35 -14
- package/lib/vendor/blamejs/lib/network-proxy.js +42 -4
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +1 -1
- package/lib/vendor/blamejs/lib/network-tls.js +341 -11
- package/lib/vendor/blamejs/lib/nist-crosswalk.js +2 -2
- package/lib/vendor/blamejs/lib/ntp-check.js +30 -19
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +1 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +1 -1
- package/lib/vendor/blamejs/lib/object-store/http-put.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -5
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +2 -2
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +4 -2
- package/lib/vendor/blamejs/lib/openapi.js +1 -1
- package/lib/vendor/blamejs/lib/pqc-agent.js +4 -7
- package/lib/vendor/blamejs/lib/problem-details.js +2 -1
- package/lib/vendor/blamejs/lib/redis-client.js +12 -1
- package/lib/vendor/blamejs/lib/regex-linear.js +1349 -0
- package/lib/vendor/blamejs/lib/render.js +531 -7
- package/lib/vendor/blamejs/lib/request-helpers.js +181 -5
- package/lib/vendor/blamejs/lib/router.js +37 -13
- package/lib/vendor/blamejs/lib/safe-async.js +142 -0
- package/lib/vendor/blamejs/lib/safe-icap.js +3 -0
- package/lib/vendor/blamejs/lib/safe-sql.js +15 -3
- package/lib/vendor/blamejs/lib/self-update.js +2 -2
- package/lib/vendor/blamejs/lib/testing.js +54 -7
- package/lib/vendor/blamejs/lib/validate-opts.js +56 -0
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +62 -25
- package/lib/vendor/blamejs/lib/vendor/blamejs-pki.cjs +2004 -142
- package/lib/vendor/blamejs/lib/vendor/browser/noble-ciphers.mjs +727 -0
- package/lib/vendor/blamejs/lib/vendor/browser/noble-hashes.mjs +1070 -0
- package/lib/vendor/blamejs/lib/vendor/browser/noble-post-quantum.mjs +1090 -0
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +510 -227
- package/lib/vendor/blamejs/lib/webhook-hmac.js +19 -2
- package/lib/vendor/blamejs/lib/webhook.js +1 -1
- package/lib/vendor/blamejs/lib/ws-client.js +24 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/sbom.cdx.json +6 -6
- package/lib/webhook-receiver.js +43 -73
- package/package.json +1 -1
package/lib/site-redirects.js
CHANGED
|
@@ -240,18 +240,29 @@ function _epochMs(n, label) {
|
|
|
240
240
|
return n;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
// backtracking under adversarial input. Operators wanting these
|
|
247
|
-
// shapes register multiple `prefix` / `exact` rules instead — the
|
|
248
|
-
// regex match_kind is for cheap path-translation, not arbitrary
|
|
249
|
-
// pattern matching.
|
|
243
|
+
// Compile an operator's redirect pattern, anchored with `^` and `$` so
|
|
244
|
+
// `resolveForPath` answers an exact-path match rather than a substring one
|
|
245
|
+
// (`/foo` must not find `/foo/bar`).
|
|
250
246
|
//
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
247
|
+
// The pattern is matched by b.regexLinear, which simulates every path through
|
|
248
|
+
// it one character at a time, so the work cannot grow faster than the subject
|
|
249
|
+
// times the pattern no matter what the operator wrote. That replaces the
|
|
250
|
+
// screen this used to run — a walker for backreferences and lookaround, then
|
|
251
|
+
// b.guardRegex for backtracking shapes.
|
|
252
|
+
//
|
|
253
|
+
// Screening was always an approximation in both directions: it refused
|
|
254
|
+
// patterns that were perfectly linear, and it could not promise to catch every
|
|
255
|
+
// shape that was not, so each shape it missed became another case to add. The
|
|
256
|
+
// patterns it existed to stop — `(a+)+`, `(a|a)*` — are now simply run: on two
|
|
257
|
+
// thousand characters they finish in about two milliseconds where the platform
|
|
258
|
+
// engine takes the better part of a minute. An operator gets their pattern
|
|
259
|
+
// accepted and the request path stays bounded, which is what the screen was
|
|
260
|
+
// trying and failing to deliver.
|
|
261
|
+
//
|
|
262
|
+
// Three constructs still cannot be simulated this way and are refused by name:
|
|
263
|
+
// a backreference, a lookaround, and a repetition whose body can match nothing.
|
|
264
|
+
// Each is mapped below into this module's TypeError envelope so a caller sees
|
|
265
|
+
// one error shape.
|
|
255
266
|
function _compileRegex(source) {
|
|
256
267
|
if (typeof source !== "string" || !source.length) {
|
|
257
268
|
throw new TypeError("siteRedirects: source_path (regex) must be a non-empty string");
|
|
@@ -264,124 +275,36 @@ function _compileRegex(source) {
|
|
|
264
275
|
if (CONTROL_BYTE_RE.test(source) || ZERO_WIDTH_RE.test(source)) {
|
|
265
276
|
throw new TypeError("siteRedirects: regex source contains control / zero-width bytes");
|
|
266
277
|
}
|
|
267
|
-
// Backreferences: \1 .. \9 outside a character class. The walker
|
|
268
|
-
// tracks character-class depth so `[\1]` (literal byte) doesn't
|
|
269
|
-
// trip the gate, but `(.)\1` (a real backreference) does.
|
|
270
|
-
var inClass = 0;
|
|
271
|
-
for (var i = 0; i < source.length; i += 1) {
|
|
272
|
-
var ch = source.charAt(i);
|
|
273
|
-
if (ch === "\\" && i + 1 < source.length) {
|
|
274
|
-
var nxt = source.charAt(i + 1);
|
|
275
|
-
if (inClass === 0 && nxt >= "1" && nxt <= "9") {
|
|
276
|
-
throw new TypeError(
|
|
277
|
-
"siteRedirects: regex backreferences (\\1..\\9) refused — operators register " +
|
|
278
|
-
"separate redirect rows for each variant instead"
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
i += 1; // skip escaped char
|
|
282
|
-
continue;
|
|
283
|
-
}
|
|
284
|
-
if (ch === "[") { inClass += 1; continue; }
|
|
285
|
-
if (ch === "]" && inClass > 0) { inClass -= 1; continue; }
|
|
286
|
-
if (inClass > 0) continue;
|
|
287
|
-
if (ch === "(" && i + 2 < source.length && source.charAt(i + 1) === "?") {
|
|
288
|
-
var third = source.charAt(i + 2);
|
|
289
|
-
if (third === "=" || third === "!" || third === "<") {
|
|
290
|
-
throw new TypeError(
|
|
291
|
-
"siteRedirects: regex lookahead / lookbehind (`(?=`, `(?!`, `(?<=`, `(?<!`) refused " +
|
|
292
|
-
"— catastrophic-backtracking surface; rewrite as `prefix` or split into multiple rows"
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
// Build the anchored form. RegExp() throws SyntaxError on a
|
|
298
|
-
// malformed source — re-shape that into the primitive's TypeError
|
|
299
|
-
// envelope so callers can match on the consistent error shape.
|
|
300
278
|
var anchored = "^(?:" + source + ")$";
|
|
301
|
-
var compiled;
|
|
302
279
|
try {
|
|
303
|
-
|
|
280
|
+
return b.regexLinear.compile(anchored);
|
|
304
281
|
} catch (e) {
|
|
282
|
+
var code = (e && e.code) || "";
|
|
283
|
+
if (code === "regex/unsupported-backreference") {
|
|
284
|
+
throw new TypeError(
|
|
285
|
+
"siteRedirects: regex backreferences (\\1..\\9) refused — a backreference " +
|
|
286
|
+
"cannot be matched in linear time; register a separate redirect row for " +
|
|
287
|
+
"each variant instead"
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
if (code === "regex/unsupported-lookaround") {
|
|
291
|
+
throw new TypeError(
|
|
292
|
+
"siteRedirects: regex lookahead / lookbehind (`(?=`, `(?!`, `(?<=`, `(?<!`) " +
|
|
293
|
+
"refused — lookaround cannot be matched in linear time; rewrite as `prefix` " +
|
|
294
|
+
"or split into multiple rows"
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
if (code === "regex/nullable-repetition") {
|
|
298
|
+
throw new TypeError(
|
|
299
|
+
"siteRedirects: a repetition whose body can match nothing (`(a*)*`) is " +
|
|
300
|
+
"refused — it matches exactly what its body matches, so write that instead"
|
|
301
|
+
);
|
|
302
|
+
}
|
|
305
303
|
throw new TypeError(
|
|
306
304
|
"siteRedirects: regex source did not compile — " +
|
|
307
305
|
(e && e.message ? e.message : "invalid pattern")
|
|
308
306
|
);
|
|
309
307
|
}
|
|
310
|
-
// Extend the backreference / lookaround screen above with the last
|
|
311
|
-
// catastrophic-backtracking class it doesn't cover: a nested unbounded
|
|
312
|
-
// quantifier ((a+)+, (a*)*, (?:a+)+, (.+)+ …). This regex runs against the
|
|
313
|
-
// request path in `resolveForPath`, so a super-linear pattern is a DoS on
|
|
314
|
-
// every matching request. (The framework's b.guardRegex screen is not used
|
|
315
|
-
// here because its text scan misreads the `?` in a `(?:…)` group prefix and
|
|
316
|
-
// a bounded trailing `?` as quantifiers, rejecting linear patterns like
|
|
317
|
-
// `/blog(?:/page/\d+)?` — filed upstream; this walker allows them.)
|
|
318
|
-
if (_hasNestedUnboundedQuantifier(source)) {
|
|
319
|
-
throw new TypeError(
|
|
320
|
-
"siteRedirects: regex source rejected — nested unbounded quantifier " +
|
|
321
|
-
"(catastrophic-backtracking / ReDoS) surface; rewrite as `prefix` / " +
|
|
322
|
-
"`exact`, or split into multiple rows"
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
return compiled;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// Detect the nested-unbounded-quantifier ReDoS class: a group whose body
|
|
329
|
-
// contains an unbounded quantifier (`+`, `*`, `{n,}`) and is itself repeated
|
|
330
|
-
// by an unbounded quantifier — `(a+)+`, `(a*)*`, `(?:a+)+`, `(.+)+`,
|
|
331
|
-
// `((ab)+)+` at any depth. A single optional / linearly-repeated group
|
|
332
|
-
// (`(?:foo)?`, `(?:bar)*`, `/products/.+`) is safe and MUST be allowed. The
|
|
333
|
-
// walk mirrors the backreference/lookaround walk: char-by-char, honoring
|
|
334
|
-
// escapes, character classes, and the `(?:` / `(?<name>` group prefixes whose
|
|
335
|
-
// `?` is group syntax, not a quantifier. Lookaround is already refused before
|
|
336
|
-
// this runs, so only `(?:` reaches here.
|
|
337
|
-
function _hasNestedUnboundedQuantifier(source) {
|
|
338
|
-
var stack = []; // open groups: { bodyUnbounded: bool }
|
|
339
|
-
var inClass = false;
|
|
340
|
-
var i = 0;
|
|
341
|
-
var n = source.length;
|
|
342
|
-
function outerUnboundedAt(idx) {
|
|
343
|
-
var c = source.charAt(idx);
|
|
344
|
-
if (c === "*" || c === "+") return true;
|
|
345
|
-
if (c === "{") { return /^\{\d*,\}/.test(source.slice(idx)); } // {n,} — no upper bound
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
while (i < n) {
|
|
349
|
-
var ch = source.charAt(i);
|
|
350
|
-
if (ch === "\\") { i += 2; continue; } // escaped atom
|
|
351
|
-
if (inClass) { if (ch === "]") { inClass = false; } i += 1; continue; }
|
|
352
|
-
if (ch === "[") { inClass = true; i += 1; continue; }
|
|
353
|
-
if (ch === "(") {
|
|
354
|
-
if (source.charAt(i + 1) === "?") { // group prefix — not a quantifier
|
|
355
|
-
i += 2;
|
|
356
|
-
if (source.charAt(i) === ":") { i += 1; }
|
|
357
|
-
else if (source.charAt(i) === "<") { while (i < n && source.charAt(i) !== ">") { i += 1; } if (i < n) { i += 1; } }
|
|
358
|
-
} else { i += 1; }
|
|
359
|
-
stack.push({ bodyUnbounded: false });
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
if (ch === ")") {
|
|
363
|
-
var g = stack.pop() || { bodyUnbounded: false };
|
|
364
|
-
var outer = outerUnboundedAt(i + 1);
|
|
365
|
-
if (g.bodyUnbounded && outer) { return true; } // nested unbounded quantifier
|
|
366
|
-
// A group repeated by an unbounded quantifier is itself an unbounded
|
|
367
|
-
// atom for its parent.
|
|
368
|
-
if (outer && stack.length) { stack[stack.length - 1].bodyUnbounded = true; }
|
|
369
|
-
i += 1;
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
if (ch === "*" || ch === "+") {
|
|
373
|
-
if (stack.length) { stack[stack.length - 1].bodyUnbounded = true; }
|
|
374
|
-
i += 1;
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
if (ch === "{" && /^\{\d*,\}/.test(source.slice(i))) {
|
|
378
|
-
if (stack.length) { stack[stack.length - 1].bodyUnbounded = true; }
|
|
379
|
-
i += 1;
|
|
380
|
-
continue;
|
|
381
|
-
}
|
|
382
|
-
i += 1;
|
|
383
|
-
}
|
|
384
|
-
return false;
|
|
385
308
|
}
|
|
386
309
|
|
|
387
310
|
// ---- row hydration ------------------------------------------------------
|
package/lib/storefront.js
CHANGED
|
@@ -15928,28 +15928,26 @@ function mount(router, deps) {
|
|
|
15928
15928
|
// is built from the validated UUID order id alone (hex + hyphens),
|
|
15929
15929
|
// carrying no quote/CRLF that could break out of the header.
|
|
15930
15930
|
var safeId = String(o.id).replace(/[^A-Za-z0-9._-]/g, "");
|
|
15931
|
-
res.status(200);
|
|
15932
|
-
if (res.setHeader) {
|
|
15933
|
-
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
15934
|
-
res.setHeader("content-disposition", "attachment; filename=\"receipt-" + safeId + ".html\"");
|
|
15935
|
-
res.setHeader("x-content-type-options", "nosniff");
|
|
15936
|
-
// The receipt carries the buyer's name + address + line items —
|
|
15937
|
-
// keep it out of any shared/proxy cache.
|
|
15938
|
-
res.setHeader("cache-control", "no-store");
|
|
15939
|
-
}
|
|
15940
15931
|
// One chunk per batch as the source yields it — bounded memory
|
|
15941
|
-
// regardless of document size.
|
|
15942
|
-
//
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
|
|
15946
|
-
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
|
|
15932
|
+
// regardless of document size. render.stream awaits backpressure so a
|
|
15933
|
+
// slow client cannot queue the whole document in the socket buffer,
|
|
15934
|
+
// stops when the peer disconnects, and signals a mid-stream failure as
|
|
15935
|
+
// a broken transfer rather than ending a truncated body as a clean 200.
|
|
15936
|
+
//
|
|
15937
|
+
// Headers go in the call, not via setHeader beforehand: render.stream
|
|
15938
|
+
// writes its own defaults with the first chunk, and its default
|
|
15939
|
+
// Content-Type would replace one set earlier. Cache-Control is set
|
|
15940
|
+
// explicitly because the receipt carries the buyer's name, address and
|
|
15941
|
+
// line items and must stay out of any shared or proxy cache.
|
|
15942
|
+
await b.render.stream(res, _streamReceiptDocument(doc), {
|
|
15943
|
+
status: 200,
|
|
15944
|
+
headers: {
|
|
15945
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
15946
|
+
"Content-Disposition": "attachment; filename=\"receipt-" + safeId + ".html\"",
|
|
15947
|
+
"X-Content-Type-Options": "nosniff",
|
|
15948
|
+
"Cache-Control": "no-store",
|
|
15949
|
+
},
|
|
15950
|
+
});
|
|
15953
15951
|
});
|
|
15954
15952
|
}
|
|
15955
15953
|
|