@blamejs/blamejs-shop 0.5.20 → 0.5.22

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -0
  3. package/SECURITY.md +23 -0
  4. package/lib/addresses.js +17 -3
  5. package/lib/admin.js +14 -5
  6. package/lib/affiliates.js +7 -23
  7. package/lib/announcement-bar.js +5 -22
  8. package/lib/api-keys.js +4 -13
  9. package/lib/asset-manifest.json +1 -1
  10. package/lib/banner-ab-tests.js +5 -9
  11. package/lib/blog-articles.js +8 -26
  12. package/lib/captcha-gate.js +7 -17
  13. package/lib/carrier-accounts.js +3 -10
  14. package/lib/catalog-drafts.js +5 -12
  15. package/lib/category-navigation.js +7 -20
  16. package/lib/cms-blocks.js +4 -7
  17. package/lib/compliance-export.js +11 -11
  18. package/lib/consent-ledger.js +2 -4
  19. package/lib/cost-layers.js +56 -21
  20. package/lib/customer-import.js +2 -2
  21. package/lib/customer-notes.js +7 -23
  22. package/lib/customer-roles.js +3 -5
  23. package/lib/customer-segments.js +17 -14
  24. package/lib/customer-surveys.js +7 -14
  25. package/lib/customers.js +2 -4
  26. package/lib/dispute-resolution.js +5 -13
  27. package/lib/dropship-forwarding.js +3 -5
  28. package/lib/dunning.js +2 -7
  29. package/lib/email-ab-tests.js +4 -8
  30. package/lib/email-campaigns.js +39 -15
  31. package/lib/email-warmup.js +2 -7
  32. package/lib/experiments.js +6 -10
  33. package/lib/externaldb-d1.js +47 -31
  34. package/lib/geolocation.js +18 -28
  35. package/lib/gift-options.js +5 -23
  36. package/lib/knowledge-base.js +7 -22
  37. package/lib/line-gift-wrap.js +7 -17
  38. package/lib/live-chat.js +5 -18
  39. package/lib/metered-usage.js +3 -8
  40. package/lib/notifications.js +3 -7
  41. package/lib/operator-accounts.js +3 -5
  42. package/lib/operator-approvals.js +6 -8
  43. package/lib/operator-audit-log.js +2 -7
  44. package/lib/operator-help-center.js +5 -21
  45. package/lib/operator-inbox.js +4 -11
  46. package/lib/operator-roles.js +5 -7
  47. package/lib/order-escalation.js +2 -2
  48. package/lib/order-export.js +24 -20
  49. package/lib/order-notes.js +4 -14
  50. package/lib/order-ratings.js +4 -10
  51. package/lib/payment-methods.js +5 -13
  52. package/lib/payment-retries.js +2 -7
  53. package/lib/pixel-events.js +21 -28
  54. package/lib/plan-changes.js +2 -7
  55. package/lib/product-qa.js +4 -8
  56. package/lib/promo-banners.js +7 -15
  57. package/lib/purchase-orders.js +3 -6
  58. package/lib/push-notifications.js +7 -32
  59. package/lib/pwa-manifest.js +6 -11
  60. package/lib/quotes.js +5 -9
  61. package/lib/reviews.js +4 -10
  62. package/lib/robots-config.js +6 -14
  63. package/lib/sales-tax-filings.js +2 -2
  64. package/lib/search-facets.js +5 -5
  65. package/lib/search-ranking.js +4 -7
  66. package/lib/search-synonyms.js +7 -21
  67. package/lib/security-middleware.js +86 -58
  68. package/lib/seller-signup.js +10 -26
  69. package/lib/sidebar-widgets.js +6 -15
  70. package/lib/site-redirects.js +5 -16
  71. package/lib/sitemap-generator.js +3 -7
  72. package/lib/sms-dispatcher.js +7 -23
  73. package/lib/stock-receipts.js +4 -10
  74. package/lib/storefront-dashboards.js +2 -10
  75. package/lib/storefront-forms.js +9 -22
  76. package/lib/storefront-pages.js +6 -20
  77. package/lib/storefront.js +2 -2
  78. package/lib/subscription-billing.js +3 -8
  79. package/lib/subscription-controls.js +2 -7
  80. package/lib/suggestion-box.js +9 -26
  81. package/lib/support-tickets.js +6 -24
  82. package/lib/tax-remittance.js +2 -2
  83. package/lib/tenants.js +2 -7
  84. package/lib/text-guard.js +179 -35
  85. package/lib/theme-assets.js +4 -16
  86. package/lib/translations.js +3 -6
  87. package/lib/trust-badges.js +4 -7
  88. package/lib/vendor/MANIFEST.json +12 -12
  89. package/lib/vendor/blamejs/CHANGELOG.md +32 -0
  90. package/lib/vendor/blamejs/NOTICE +1 -1
  91. package/lib/vendor/blamejs/README.md +1 -1
  92. package/lib/vendor/blamejs/lib/network-tls.js +98 -13
  93. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +12 -12
  94. package/lib/vendor/blamejs/lib/vendor/blamejs-pki.cjs +568 -304
  95. package/lib/vendor/blamejs/package.json +1 -1
  96. package/lib/vendor/blamejs/sbom.cdx.json +6 -6
  97. package/lib/vendor-invoices.js +3 -6
  98. package/lib/vendors.js +5 -19
  99. package/lib/webhook-receiver.js +3 -10
  100. package/lib/webhook-subscriptions.js +3 -13
  101. package/lib/wishlist-sharing.js +5 -10
  102. package/package.json +1 -1
@@ -1610,6 +1610,23 @@ function _verifyOcspSignature(parsed, issuerPem) {
1610
1610
  throw new TlsTrustError("tls/ocsp-bad-issuer-key",
1611
1611
  "issuer public key parse failed: " + ((e && e.message) || String(e)));
1612
1612
  }
1613
+ // RFC 6960 §4.2.1 — signatureAlgorithm identifies the algorithm the
1614
+ // responder used, and the digest above is derived from it. node:crypto picks
1615
+ // RSA or ECDSA from the KEY, not from that field, so a response declaring
1616
+ // one and carrying the other verifies without anyone noticing the
1617
+ // disagreement. That is not a forgery path — the issuer's private key is
1618
+ // required either way — but it means the field steering the digest was never
1619
+ // checked against the key doing the verifying. Require them to agree, so
1620
+ // what the response claims and what was actually verified are the same
1621
+ // thing.
1622
+ var wantKeyType = (algOid === OID_RSA_SHA256 || algOid === OID_RSA_SHA384 ||
1623
+ algOid === OID_RSA_SHA512) ? "rsa" : "ec";
1624
+ if (keyObj.asymmetricKeyType !== wantKeyType) {
1625
+ throw new TlsTrustError("tls/ocsp-sig-alg-key-mismatch",
1626
+ "OCSP signatureAlgorithm OID '" + algOid + "' declares a " + wantKeyType.toUpperCase() +
1627
+ " signature but the issuer key is " + String(keyObj.asymmetricKeyType).toUpperCase() +
1628
+ " (RFC 6960 §4.2.1 — the declared algorithm does not match the issuer key)");
1629
+ }
1613
1630
  // ECDSA OCSP signatures use DER-encoded ECDSA-Sig-Value (the ASN.1
1614
1631
  // shape that node:crypto.verify accepts by default — no dsaEncoding
1615
1632
  // option needed).
@@ -2831,13 +2848,19 @@ function _ctVerifyInclusionPath(leafHash, leafIndex, treeSize, auditPath) {
2831
2848
  // prefix. Returns the computed roots (oldRoot, newRoot) so the caller
2832
2849
  // can compare against the operator-supplied STHs.
2833
2850
  function _ctVerifyConsistencyPath(m, n, consistencyProof, firstHash) {
2834
- if (typeof m !== "number" || m < 1 || Math.floor(m) !== m) {
2851
+ // isFinite carries the weight here: Math.floor(Infinity) === Infinity, so an
2852
+ // integer check alone accepts a tree of infinite size. The walk used to
2853
+ // reject it downstream by running out of proof, but that was an accident of
2854
+ // the loop rather than a decision, and the equal-sizes shortcut below has no
2855
+ // loop to run out of. A tree size that is not a finite positive integer is
2856
+ // refused here, once, for every path through this function.
2857
+ if (typeof m !== "number" || !isFinite(m) || m < 1 || Math.floor(m) !== m) {
2835
2858
  throw new TlsTrustError("tls/ct-bad-first-size",
2836
- "ct.verifyConsistency: m (first tree size) must be a positive integer");
2859
+ "ct.verifyConsistency: m (first tree size) must be a finite positive integer");
2837
2860
  }
2838
- if (typeof n !== "number" || n < m || Math.floor(n) !== n) {
2861
+ if (typeof n !== "number" || !isFinite(n) || n < m || Math.floor(n) !== n) {
2839
2862
  throw new TlsTrustError("tls/ct-bad-second-size",
2840
- "ct.verifyConsistency: n (second tree size) must be an integer >= m");
2863
+ "ct.verifyConsistency: n (second tree size) must be a finite integer >= m");
2841
2864
  }
2842
2865
  if (!Buffer.isBuffer(firstHash) || firstHash.length !== 32) { // RFC 9162 SHA-256 digest length
2843
2866
  throw new TlsTrustError("tls/ct-bad-first-hash",
@@ -2847,11 +2870,34 @@ function _ctVerifyConsistencyPath(m, n, consistencyProof, firstHash) {
2847
2870
  throw new TlsTrustError("tls/ct-bad-consistency-proof",
2848
2871
  "ct.verifyConsistency: consistencyProof must be an array of Buffers");
2849
2872
  }
2850
- // RFC 9162 §2.1.4.2 — algorithm is the same as the inclusion-proof
2851
- // walk, with the leaf-index seeded at the first-tree size minus 1 and
2852
- // the special case for m being a complete subtree.
2873
+ // A tree is consistent with itself, and RFC 9162 §2.1.4 says so with an
2874
+ // EMPTY proof: PROOF(m, D[m]) = SUBPROOF(m, D[m], true) = {}. The walk below
2875
+ // is §2.1.4.2, which is written for a first tree strictly smaller than the
2876
+ // second — run on m === n it looks for a sibling that the definition says is
2877
+ // not there. That refused a conformant log's answer whenever the size was
2878
+ // not a power of two (for a power of two the index bits happen to shift down
2879
+ // to zero and the walk short-circuits), so an operator re-checking a pinned
2880
+ // STH against an unchanged one was told the log was inconsistent. A false
2881
+ // alarm on this check is worse than a quiet one: it is the alarm that
2882
+ // teaches an operator to ignore it.
2883
+ if (m === n) {
2884
+ if (consistencyProof.length !== 0) {
2885
+ throw new TlsTrustError("tls/ct-consistency-not-empty",
2886
+ "ct.verifyConsistency: the proof for two equal tree sizes must be empty " +
2887
+ "(RFC 9162 §2.1.4), got " + consistencyProof.length + " entries");
2888
+ }
2889
+ return firstHash;
2890
+ }
2891
+ // RFC 9162 §2.1.4.2 — the walk rebuilds BOTH roots from the same proof: the
2892
+ // first tree's root (fr) and the second's (sr). Both must be checked. Only
2893
+ // sr was, and firstHash reached the computation solely as the seed in the
2894
+ // complete-subtree branch below — so whenever the pinned size was NOT a
2895
+ // power of two, the operator's pinned root was never looked at, and a proof
2896
+ // for some OTHER first tree of the same size verified. That is the whole
2897
+ // premise of pinning an STH ("the tree I pinned is a prefix of the tree you
2898
+ // are showing me"), and it was being taken on trust.
2853
2899
  var path = consistencyProof.slice();
2854
- var node;
2900
+ var firstNode, secondNode;
2855
2901
  var fn = m - 1;
2856
2902
  var sn = n - 1;
2857
2903
  // Walk past the right-side bits — the consistency proof omits the
@@ -2860,14 +2906,15 @@ function _ctVerifyConsistencyPath(m, n, consistencyProof, firstHash) {
2860
2906
 
2861
2907
  if (fn === 0) {
2862
2908
  // m was a complete subtree — its root is the firstHash itself.
2863
- node = firstHash;
2909
+ firstNode = firstHash;
2864
2910
  } else {
2865
2911
  if (path.length === 0) {
2866
2912
  throw new TlsTrustError("tls/ct-consistency-empty",
2867
2913
  "ct.verifyConsistency: consistency proof empty but first tree is not a complete subtree");
2868
2914
  }
2869
- node = path.shift();
2915
+ firstNode = path.shift();
2870
2916
  }
2917
+ secondNode = firstNode;
2871
2918
  while (sn > 0) {
2872
2919
  if (path.length === 0) {
2873
2920
  throw new TlsTrustError("tls/ct-consistency-short",
@@ -2879,15 +2926,34 @@ function _ctVerifyConsistencyPath(m, n, consistencyProof, firstHash) {
2879
2926
  "ct.verifyConsistency: consistency-proof entry is not a 32-byte Buffer");
2880
2927
  }
2881
2928
  if ((fn & 1) === 1 || fn === sn) {
2882
- node = _ctInnerHashFinal(sibling, node);
2929
+ firstNode = _ctInnerHashFinal(sibling, firstNode);
2930
+ secondNode = _ctInnerHashFinal(sibling, secondNode);
2883
2931
  while ((fn & 1) === 0 && fn !== 0) { fn >>>= 1; sn >>>= 1; }
2884
2932
  } else {
2885
- node = _ctInnerHashFinal(node, sibling);
2933
+ secondNode = _ctInnerHashFinal(secondNode, sibling);
2886
2934
  }
2887
2935
  fn >>>= 1;
2888
2936
  sn >>>= 1;
2889
2937
  }
2890
- return node;
2938
+ // The rebuilt first root must be the one the operator pinned, or the proof
2939
+ // connects their second root to a first tree they never saw.
2940
+ if (firstNode.length !== firstHash.length ||
2941
+ !bCrypto.timingSafeEqual(firstNode, firstHash)) {
2942
+ throw new TlsTrustError("tls/ct-first-root-mismatch",
2943
+ "ct.verifyConsistency: the proof rebuilds a first-tree root that is not the one supplied " +
2944
+ "(RFC 9162 §2.1.4.2 — the proof does not connect the pinned tree to the new one)");
2945
+ }
2946
+ // Everything the peer sent must have been consumed. Its sibling walk above
2947
+ // refuses an audit path with entries beyond the root for the same reason:
2948
+ // a proof carrying material the verifier never looked at is not the proof
2949
+ // the operator believes was checked, and silently ignoring the remainder
2950
+ // means the two walkers disagree about what a well-formed proof is.
2951
+ if (path.length !== 0) {
2952
+ throw new TlsTrustError("tls/ct-consistency-long",
2953
+ "ct.verifyConsistency: consistency proof has " + path.length +
2954
+ " trailing entries beyond the second-tree root");
2955
+ }
2956
+ return secondNode;
2891
2957
  }
2892
2958
 
2893
2959
  function _findSctOid(rawDer) {
@@ -3087,6 +3153,15 @@ var ct = Object.freeze({
3087
3153
  consistency: consistencyResult };
3088
3154
  }
3089
3155
  } catch (e) {
3156
+ // A proof that rebuilds the wrong first tree is a different answer
3157
+ // from a malformed one, and it is the answer that matters most here:
3158
+ // it says the log's history before the pinned point does not match
3159
+ // what was pinned. Composing the consistency check inside an
3160
+ // inclusion check must not flatten that into "malformed proof".
3161
+ if (e && e.code === "tls/ct-first-root-mismatch") {
3162
+ return { valid: false, reason: "first-root-mismatch",
3163
+ error: e.message || String(e) };
3164
+ }
3090
3165
  return { valid: false, reason: "consistency-walk-failed",
3091
3166
  error: (e && e.message) || String(e) };
3092
3167
  }
@@ -3128,6 +3203,16 @@ var ct = Object.freeze({
3128
3203
  computed = _ctVerifyConsistencyPath(opts.firstSize, opts.secondSize,
3129
3204
  opts.proof || [], firstRoot);
3130
3205
  } catch (e) {
3206
+ // A first root that does not rebuild is a distinct answer from a
3207
+ // malformed proof: the proof is well-formed, it just describes a
3208
+ // different tree than the one the operator pinned.
3209
+ // `e` is already proven truthy by the guard on this branch, so the
3210
+ // usual (e && e.message) shape would be dead here; the fallback below
3211
+ // keeps it because a throw of a falsy value still reaches that one.
3212
+ if (e && e.code === "tls/ct-first-root-mismatch") {
3213
+ return { valid: false, reason: "first-root-mismatch",
3214
+ error: e.message || String(e) };
3215
+ }
3131
3216
  return { valid: false, reason: "consistency-walk-failed",
3132
3217
  error: (e && e.message) || String(e) };
3133
3218
  }
@@ -21,7 +21,7 @@
21
21
  "server": "sha256:f3325f480cb8eb814fcb0baaa19336cbbf2b993f48624c6aa9600ffd69d0be5e",
22
22
  "browser": "sha256:0ffd91540bcb586a29b56e52ee1c29df69097b50776beb4036a07558f7a4e12e"
23
23
  },
24
- "refreshedAt": "2026-08-10T18:39:35.028Z"
24
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
25
25
  },
26
26
  "@noble/hashes": {
27
27
  "version": "2.3.0",
@@ -48,7 +48,7 @@
48
48
  "hashes": {
49
49
  "browser": "sha256:dfe4b7ae3c9880e388c8da4b68f44742b229b53afacd1e674179527e33da62b0"
50
50
  },
51
- "refreshedAt": "2026-08-10T18:39:35.028Z"
51
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
52
52
  },
53
53
  "@noble/curves": {
54
54
  "version": "2.3.0",
@@ -70,7 +70,7 @@
70
70
  "hashes": {
71
71
  "server": "sha256:b5fe88d1ea780d0581dee6145d666f89d46fc9531b5db35db2e5b16627840890"
72
72
  },
73
- "refreshedAt": "2026-08-10T18:39:35.028Z",
73
+ "refreshedAt": "2026-08-11T00:05:07.579Z",
74
74
  "components": {
75
75
  "@noble/hashes": {
76
76
  "url": "https://github.com/paulmillr/noble-hashes",
@@ -114,7 +114,7 @@
114
114
  "server": "sha256:fab7ebe5737793862c473444f4ee5912f79dd1edec86683acbb4eecbca0f5892",
115
115
  "browser": "sha256:cae1d5bbdc7184b202b6ca68df6e1db7b0d0f668c77809ded189ca7f271accc9"
116
116
  },
117
- "refreshedAt": "2026-08-10T18:39:35.028Z",
117
+ "refreshedAt": "2026-08-11T00:05:07.579Z",
118
118
  "components": {
119
119
  "@noble/hashes": {
120
120
  "url": "https://github.com/paulmillr/noble-hashes",
@@ -151,7 +151,7 @@
151
151
  "hashes": {
152
152
  "server": "sha256:e83195dc9f189385da9c856ef38843f4466f93ea8f3d7fc2efcb1e1b18da6f20"
153
153
  },
154
- "refreshedAt": "2026-08-10T18:39:35.028Z"
154
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
155
155
  },
156
156
  "SecLists-common-passwords-top-10000": {
157
157
  "version": "10k-most-common (master)",
@@ -171,7 +171,7 @@
171
171
  },
172
172
  "runtime_artifact": "lib/vendor/common-passwords-top-10000.data.js",
173
173
  "integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
174
- "refreshedAt": "2026-08-10T18:39:35.028Z"
174
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
175
175
  },
176
176
  "bimi-trust-anchors": {
177
177
  "version": "operator-managed",
@@ -196,7 +196,7 @@
196
196
  },
197
197
  "runtime_artifact": "lib/vendor/bimi-trust-anchors.data.js",
198
198
  "integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
199
- "refreshedAt": "2026-08-10T18:39:35.028Z"
199
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
200
200
  },
201
201
  "publicsuffix-list": {
202
202
  "version": "master",
@@ -216,10 +216,10 @@
216
216
  },
217
217
  "runtime_artifact": "lib/vendor/public-suffix-list.data.js",
218
218
  "integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
219
- "refreshedAt": "2026-08-10T18:39:35.028Z"
219
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
220
220
  },
221
221
  "@blamejs/pki": {
222
- "version": "0.4.13",
222
+ "version": "0.4.14",
223
223
  "license": "Apache-2.0",
224
224
  "author": "blamejs",
225
225
  "source": "https://github.com/blamejs/pki",
@@ -240,11 +240,11 @@
240
240
  },
241
241
  "bundler": "esbuild --format=cjs --platform=node --external:crypto --external:node:crypto",
242
242
  "bundledAt": "2026-08-10T00:00:00Z",
243
- "cpe": "cpe:2.3:a:blamejs:pki:0.4.13:*:*:*:*:node.js:*:*",
243
+ "cpe": "cpe:2.3:a:blamejs:pki:0.4.14:*:*:*:*:node.js:*:*",
244
244
  "hashes": {
245
- "server": "sha256:067ac05899ef04f7851a8d010dc4289e7a01706d5fd2cdc1ce59860631bba284"
245
+ "server": "sha256:96a873b733c95b53b8e2ced065a82192b6acabcede312cf68a45a128857cc3bc"
246
246
  },
247
- "refreshedAt": "2026-08-10T18:39:35.028Z"
247
+ "refreshedAt": "2026-08-11T00:05:07.579Z"
248
248
  }
249
249
  }
250
250
  }