@blamejs/blamejs-shop 0.5.20 → 0.5.21

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 (93) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +1 -0
  3. package/SECURITY.md +17 -0
  4. package/lib/addresses.js +2 -2
  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 +4 -20
  16. package/lib/cms-blocks.js +4 -7
  17. package/lib/compliance-export.js +4 -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 +25 -14
  31. package/lib/email-warmup.js +2 -7
  32. package/lib/experiments.js +6 -10
  33. package/lib/externaldb-d1.js +47 -23
  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 +3 -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 +8 -23
  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 +137 -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-invoices.js +3 -6
  89. package/lib/vendors.js +5 -19
  90. package/lib/webhook-receiver.js +3 -10
  91. package/lib/webhook-subscriptions.js +3 -13
  92. package/lib/wishlist-sharing.js +5 -10
  93. package/package.json +1 -1
@@ -68,10 +68,6 @@ var WILDCARD_EVENT = "*";
68
68
  // control bytes are a slipping-class for header injection + visual
69
69
  // spoofing downstream. Spelled with \u-escapes so ESLint's
70
70
  // no-irregular-whitespace stays happy.
71
- var CONTROL_BYTE_RE = /[\x00-\x1f\x7f]/;
72
- var ZERO_WIDTH_RE = new RegExp(
73
- "[\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u2069\\uFEFF\\u061C]"
74
- );
75
71
 
76
72
  // Event-type identifier shape — `domain.action[.qualifier]` segments
77
73
  // of ASCII letters / digits / underscore, joined by `.`. The wildcard
@@ -111,9 +107,7 @@ function _ownerId(s) {
111
107
  if (s.length > MAX_OWNER_ID_LEN) {
112
108
  throw new TypeError("webhookSubscriptions: owner_id must be <= " + MAX_OWNER_ID_LEN + " characters");
113
109
  }
114
- if (CONTROL_BYTE_RE.test(s) || ZERO_WIDTH_RE.test(s)) {
115
- throw new TypeError("webhookSubscriptions: owner_id contains control / zero-width bytes");
116
- }
110
+ textGuard.freeText(s, "webhookSubscriptions: owner_id", { singleLine: "reject", zeroWidth: "reject" });
117
111
  return s;
118
112
  }
119
113
 
@@ -191,9 +185,7 @@ function _name(s) {
191
185
  if (s.length > MAX_NAME_LEN) {
192
186
  throw new TypeError("webhookSubscriptions: name must be <= " + MAX_NAME_LEN + " characters");
193
187
  }
194
- if (CONTROL_BYTE_RE.test(s) || ZERO_WIDTH_RE.test(s)) {
195
- throw new TypeError("webhookSubscriptions: name contains control / zero-width bytes");
196
- }
188
+ textGuard.freeText(s, "webhookSubscriptions: name", { singleLine: "reject", zeroWidth: "reject" });
197
189
  return s;
198
190
  }
199
191
 
@@ -219,9 +211,7 @@ function _signingSecret(s) {
219
211
  if (s.length > 512) {
220
212
  throw new TypeError("webhookSubscriptions: signing_secret must be <= 512 characters");
221
213
  }
222
- if (CONTROL_BYTE_RE.test(s) || ZERO_WIDTH_RE.test(s)) {
223
- throw new TypeError("webhookSubscriptions: signing_secret contains control / zero-width bytes");
224
- }
214
+ textGuard.freeText(s, "webhookSubscriptions: signing_secret", { singleLine: "reject", zeroWidth: "reject" });
225
215
  return s;
226
216
  }
227
217
 
@@ -63,6 +63,7 @@
63
63
  */
64
64
 
65
65
  var b = require("./vendor/blamejs");
66
+ var textGuard = require("./text-guard");
66
67
  var wishlistModule = require("./wishlist");
67
68
 
68
69
  // ---- constants ----------------------------------------------------------
@@ -82,8 +83,6 @@ var MAX_REASON_LEN = 500;
82
83
  var MAX_EMAIL_LEN = 254;
83
84
  var MAX_MEMBER_EMAILS = 50;
84
85
 
85
- var CONTROL_BYTE_RE = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/;
86
- var CONTROL_BYTE_STRICT_RE = /[\x00-\x1f\x7f]/;
87
86
 
88
87
  // Conservative single-line email shape — defence in depth against
89
88
  // header-injection / control-byte smuggling when the operator
@@ -127,7 +126,7 @@ function _title(s, label) {
127
126
  if (typeof s !== "string" || s.length > MAX_TITLE_LEN) {
128
127
  throw new TypeError("wishlistSharing: " + label + " must be a string <= " + MAX_TITLE_LEN + " chars");
129
128
  }
130
- if (CONTROL_BYTE_RE.test(s)) {
129
+ if (textGuard.hasCodepointThreat(s)) {
131
130
  throw new TypeError("wishlistSharing: " + label + " must not contain control bytes");
132
131
  }
133
132
  return s;
@@ -137,7 +136,7 @@ function _requiredTitle(s, label) {
137
136
  if (typeof s !== "string" || !s.length || s.length > MAX_TITLE_LEN) {
138
137
  throw new TypeError("wishlistSharing: " + label + " must be a non-empty string <= " + MAX_TITLE_LEN + " chars");
139
138
  }
140
- if (CONTROL_BYTE_RE.test(s)) {
139
+ if (textGuard.hasCodepointThreat(s)) {
141
140
  throw new TypeError("wishlistSharing: " + label + " must not contain control bytes");
142
141
  }
143
142
  return s;
@@ -162,9 +161,7 @@ function _reason(s) {
162
161
  if (typeof s !== "string" || !s.length || s.length > MAX_REASON_LEN) {
163
162
  throw new TypeError("wishlistSharing: reason must be a non-empty string <= " + MAX_REASON_LEN + " chars");
164
163
  }
165
- if (CONTROL_BYTE_RE.test(s)) {
166
- throw new TypeError("wishlistSharing: reason must not contain control bytes");
167
- }
164
+ textGuard.freeText(s, "wishlistSharing: reason");
168
165
  return s;
169
166
  }
170
167
 
@@ -205,9 +202,7 @@ function _viewerSessionId(s) {
205
202
  // Session ids are opaque to this primitive; refuse control bytes
206
203
  // so the hashed breadcrumb has no log-injection vector even if a
207
204
  // downstream tool ever rendered the raw value.
208
- if (CONTROL_BYTE_STRICT_RE.test(s)) {
209
- throw new TypeError("wishlistSharing: viewer_session_id must not contain control bytes");
210
- }
205
+ textGuard.freeText(s, "wishlistSharing: viewer_session_id", { singleLine: "reject" });
211
206
  return s;
212
207
  }
213
208
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.5.20",
3
+ "version": "0.5.21",
4
4
  "description": "Open-source framework built on blamejs. Vendored stack, zero npm runtime deps, PQC-first crypto, security-on by default.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {