@rowsncolumns/utils 9.2.35 → 9.2.36

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.
@@ -64,9 +64,16 @@ export declare const supplant: (s: string, o: Record<string, any>) => string;
64
64
  /**
65
65
  * Normalize an external hyperlink target for the browser. A stored URL
66
66
  * without a scheme ("paradigm.xyz") would otherwise be resolved relative to
67
- * the current page. Prefixes https:// unless the URL already has a scheme
68
- * (https:, mailto:, tel:, …), is protocol-relative ("//host"), or is a
69
- * fragment/path reference.
67
+ * the current page. Prefixes https:// unless the URL already has a scheme,
68
+ * is protocol-relative ("//host"), or is a fragment/path reference.
69
+ *
70
+ * URLs with an explicit scheme are only passed through when the scheme is in
71
+ * the safe allowlist (http, https, mailto, tel, ftp — case-insensitive);
72
+ * anything else returns "" so it can never reach window.open/href sinks.
73
+ * Mirrors browser URL canonicalization before matching the scheme: embedded
74
+ * ASCII tab/newline characters are removed and leading/trailing C0 controls
75
+ * and whitespace are stripped, so obfuscations like "Java\tScript:" or a
76
+ * leading "\n" cannot smuggle a dangerous scheme past the check.
70
77
  * @param url
71
78
  * @returns
72
79
  */
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../string.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK3E;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,aAAa,KAAG,SAKvD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS,MAAM,EACf,UAAS;IACP,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,KACL,aAAa,GAAG,IAuDlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,uBAEvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,uBAErD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,aAAa,GAAG,IAAI,EAC1B,0BAAwB,EACxB,uBAAqB,EACrB,sBAAoB,EACpB,mBAAiB,KAChB,MAAM,GAAG,IAiBX,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,WAAW,MAAM,GAAG,SAAS,EAC7B,OAAO,SAAS,WAUjB,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,GAAG,SAAS,uBASzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,uBAgB3D,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,WAI3C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,EACpB,MAAK,aAAa,GAAG,IAAY,KAChC,SAQF,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,WAKzD,CAAC;AAKF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,WAY/C,CAAC"}
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../string.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK3E;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,aAAa,KAAG,SAKvD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS,MAAM,EACf,UAAS;IACP,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,KACL,aAAa,GAAG,IAuDlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,uBAEvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,uBAErD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,aAAa,GAAG,IAAI,EAC1B,0BAAwB,EACxB,uBAAqB,EACrB,sBAAoB,EACpB,mBAAiB,KAChB,MAAM,GAAG,IAiBX,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,WAAW,MAAM,GAAG,SAAS,EAC7B,OAAO,SAAS,WAUjB,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,GAAG,SAAS,uBASzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,uBAgB3D,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,WAI3C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,EACpB,MAAK,aAAa,GAAG,IAAY,KAChC,SAQF,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,WAKzD,CAAC;AAUF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,WAoB/C,CAAC"}
@@ -213,21 +213,40 @@ var supplant = function (s, o) {
213
213
  };
214
214
  exports.supplant = supplant;
215
215
  // RFC 3986 scheme: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) ":"
216
- var URL_SCHEME = /^[a-zA-Z][a-zA-Z0-9+.-]*:/;
216
+ var URL_SCHEME = /^([a-zA-Z][a-zA-Z0-9+.-]*):/;
217
+ // Schemes an external hyperlink is allowed to carry. Anything else with an
218
+ // explicit scheme (javascript:, data:, vbscript:, …) is a script/content
219
+ // injection vector and is rejected.
220
+ var SAFE_URL_SCHEMES = new Set(["http", "https", "mailto", "tel", "ftp"]);
217
221
  /**
218
222
  * Normalize an external hyperlink target for the browser. A stored URL
219
223
  * without a scheme ("paradigm.xyz") would otherwise be resolved relative to
220
- * the current page. Prefixes https:// unless the URL already has a scheme
221
- * (https:, mailto:, tel:, …), is protocol-relative ("//host"), or is a
222
- * fragment/path reference.
224
+ * the current page. Prefixes https:// unless the URL already has a scheme,
225
+ * is protocol-relative ("//host"), or is a fragment/path reference.
226
+ *
227
+ * URLs with an explicit scheme are only passed through when the scheme is in
228
+ * the safe allowlist (http, https, mailto, tel, ftp — case-insensitive);
229
+ * anything else returns "" so it can never reach window.open/href sinks.
230
+ * Mirrors browser URL canonicalization before matching the scheme: embedded
231
+ * ASCII tab/newline characters are removed and leading/trailing C0 controls
232
+ * and whitespace are stripped, so obfuscations like "Java\tScript:" or a
233
+ * leading "\n" cannot smuggle a dangerous scheme past the check.
223
234
  * @param url
224
235
  * @returns
225
236
  */
226
237
  var normalizeExternalUrl = function (url) {
227
- var trimmed = url.trim();
228
- if (!trimmed ||
229
- URL_SCHEME.test(trimmed) ||
230
- trimmed.startsWith("//") ||
238
+ var trimmed = url
239
+ .replace(/[\t\n\r]/g, "")
240
+ .replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, "")
241
+ .trim();
242
+ if (!trimmed) {
243
+ return "";
244
+ }
245
+ var schemeMatch = URL_SCHEME.exec(trimmed);
246
+ if (schemeMatch) {
247
+ return SAFE_URL_SCHEMES.has(schemeMatch[1].toLowerCase()) ? trimmed : "";
248
+ }
249
+ if (trimmed.startsWith("//") ||
231
250
  trimmed.startsWith("#") ||
232
251
  trimmed.startsWith("/")) {
233
252
  return trimmed;
@@ -64,9 +64,16 @@ export declare const supplant: (s: string, o: Record<string, any>) => string;
64
64
  /**
65
65
  * Normalize an external hyperlink target for the browser. A stored URL
66
66
  * without a scheme ("paradigm.xyz") would otherwise be resolved relative to
67
- * the current page. Prefixes https:// unless the URL already has a scheme
68
- * (https:, mailto:, tel:, …), is protocol-relative ("//host"), or is a
69
- * fragment/path reference.
67
+ * the current page. Prefixes https:// unless the URL already has a scheme,
68
+ * is protocol-relative ("//host"), or is a fragment/path reference.
69
+ *
70
+ * URLs with an explicit scheme are only passed through when the scheme is in
71
+ * the safe allowlist (http, https, mailto, tel, ftp — case-insensitive);
72
+ * anything else returns "" so it can never reach window.open/href sinks.
73
+ * Mirrors browser URL canonicalization before matching the scheme: embedded
74
+ * ASCII tab/newline characters are removed and leading/trailing C0 controls
75
+ * and whitespace are stripped, so obfuscations like "Java\tScript:" or a
76
+ * leading "\n" cannot smuggle a dangerous scheme past the check.
70
77
  * @param url
71
78
  * @returns
72
79
  */
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../string.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK3E;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,aAAa,KAAG,SAKvD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS,MAAM,EACf,UAAS;IACP,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,KACL,aAAa,GAAG,IAuDlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,uBAEvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,uBAErD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,aAAa,GAAG,IAAI,EAC1B,0BAAwB,EACxB,uBAAqB,EACrB,sBAAoB,EACpB,mBAAiB,KAChB,MAAM,GAAG,IAiBX,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,WAAW,MAAM,GAAG,SAAS,EAC7B,OAAO,SAAS,WAUjB,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,GAAG,SAAS,uBASzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,uBAgB3D,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,WAI3C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,EACpB,MAAK,aAAa,GAAG,IAAY,KAChC,SAQF,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,WAKzD,CAAC;AAKF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,WAY/C,CAAC"}
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../string.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK3E;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,aAAa,KAAG,SAKvD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,SAAS,MAAM,EACf,UAAS;IACP,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,KACL,aAAa,GAAG,IAuDlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,uBAEvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,uBAErD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,aAAa,GAAG,IAAI,EAC1B,0BAAwB,EACxB,uBAAqB,EACrB,sBAAoB,EACpB,mBAAiB,KAChB,MAAM,GAAG,IAiBX,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,WAAW,MAAM,GAAG,SAAS,EAC7B,OAAO,SAAS,WAUjB,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,GAAG,SAAS,uBASzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,uBAgB3D,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,WAI3C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,EACpB,MAAK,aAAa,GAAG,IAAY,KAChC,SAQF,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,WAKzD,CAAC;AAUF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,WAoB/C,CAAC"}
@@ -190,21 +190,40 @@ export const supplant = (s, o) => {
190
190
  });
191
191
  };
192
192
  // RFC 3986 scheme: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) ":"
193
- const URL_SCHEME = /^[a-zA-Z][a-zA-Z0-9+.-]*:/;
193
+ const URL_SCHEME = /^([a-zA-Z][a-zA-Z0-9+.-]*):/;
194
+ // Schemes an external hyperlink is allowed to carry. Anything else with an
195
+ // explicit scheme (javascript:, data:, vbscript:, …) is a script/content
196
+ // injection vector and is rejected.
197
+ const SAFE_URL_SCHEMES = new Set(["http", "https", "mailto", "tel", "ftp"]);
194
198
  /**
195
199
  * Normalize an external hyperlink target for the browser. A stored URL
196
200
  * without a scheme ("paradigm.xyz") would otherwise be resolved relative to
197
- * the current page. Prefixes https:// unless the URL already has a scheme
198
- * (https:, mailto:, tel:, …), is protocol-relative ("//host"), or is a
199
- * fragment/path reference.
201
+ * the current page. Prefixes https:// unless the URL already has a scheme,
202
+ * is protocol-relative ("//host"), or is a fragment/path reference.
203
+ *
204
+ * URLs with an explicit scheme are only passed through when the scheme is in
205
+ * the safe allowlist (http, https, mailto, tel, ftp — case-insensitive);
206
+ * anything else returns "" so it can never reach window.open/href sinks.
207
+ * Mirrors browser URL canonicalization before matching the scheme: embedded
208
+ * ASCII tab/newline characters are removed and leading/trailing C0 controls
209
+ * and whitespace are stripped, so obfuscations like "Java\tScript:" or a
210
+ * leading "\n" cannot smuggle a dangerous scheme past the check.
200
211
  * @param url
201
212
  * @returns
202
213
  */
203
214
  export const normalizeExternalUrl = (url) => {
204
- const trimmed = url.trim();
205
- if (!trimmed ||
206
- URL_SCHEME.test(trimmed) ||
207
- trimmed.startsWith("//") ||
215
+ const trimmed = url
216
+ .replace(/[\t\n\r]/g, "")
217
+ .replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, "")
218
+ .trim();
219
+ if (!trimmed) {
220
+ return "";
221
+ }
222
+ const schemeMatch = URL_SCHEME.exec(trimmed);
223
+ if (schemeMatch) {
224
+ return SAFE_URL_SCHEMES.has(schemeMatch[1].toLowerCase()) ? trimmed : "";
225
+ }
226
+ if (trimmed.startsWith("//") ||
208
227
  trimmed.startsWith("#") ||
209
228
  trimmed.startsWith("/")) {
210
229
  return trimmed;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowsncolumns/utils",
3
- "version": "9.2.35",
3
+ "version": "9.2.36",
4
4
  "author": "Vinay M",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "main": "./dist/cjs/index.js",