url-sanitizer 5.3.2 → 5.3.4
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/README.md +6 -6
- package/dist/url-sanitizer-wo-dompurify.min.js +1 -1
- package/dist/url-sanitizer-wo-dompurify.min.js.map +3 -3
- package/dist/url-sanitizer.min.js +3 -3
- package/dist/url-sanitizer.min.js.map +3 -3
- package/package.json +12 -11
- package/src/index.js +3 -1
- package/src/lib/iana/uri-schemes.json +1 -1
- package/src/mjs/sanitize.js +48 -12
- package/src/mjs/utility.js +3 -0
- package/types/index.d.ts +1 -1
- package/types/mjs/filter.d.ts +1 -0
- package/types/mjs/sanitize.d.ts +1 -0
package/package.json
CHANGED
|
@@ -26,31 +26,32 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"dompurify": "^3.4.16",
|
|
29
|
-
"jsdom": "^30.1.
|
|
29
|
+
"jsdom": "^30.1.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@braintree/sanitize-url": "^7.1.2",
|
|
33
33
|
"@types/jsdom": "^30.0.0",
|
|
34
|
-
"@types/node": "^26.6.
|
|
34
|
+
"@types/node": "^26.6.5",
|
|
35
35
|
"c8": "^12.0.0",
|
|
36
|
-
"chai": "^6.
|
|
36
|
+
"chai": "^6.3.0",
|
|
37
37
|
"commander": "^15.0.0",
|
|
38
|
-
"copyfiles-ng": "^2.4.
|
|
38
|
+
"copyfiles-ng": "^2.4.9",
|
|
39
39
|
"esbuild": "^0.28.2",
|
|
40
|
-
"eslint": "^10.
|
|
40
|
+
"eslint": "^10.12.0",
|
|
41
41
|
"eslint-config-prettier": "^10.1.8",
|
|
42
|
-
"eslint-plugin-jsdoc": "^
|
|
42
|
+
"eslint-plugin-jsdoc": "^65.2.2",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.6",
|
|
44
44
|
"eslint-plugin-regexp": "^3.3.1",
|
|
45
|
-
"eslint-plugin-unicorn": "^
|
|
45
|
+
"eslint-plugin-unicorn": "^77.0.0",
|
|
46
46
|
"fast-check": "^4.10.2",
|
|
47
|
-
"globals": "^17.
|
|
47
|
+
"globals": "^17.13.0",
|
|
48
48
|
"http-server": "^14.1.1",
|
|
49
49
|
"mitata": "^1.0.34",
|
|
50
|
-
"mocha": "^12.0.
|
|
51
|
-
"neostandard": "^0.14.0
|
|
50
|
+
"mocha": "^12.0.3",
|
|
51
|
+
"neostandard": "^0.14.0",
|
|
52
52
|
"papaparse": "^5.7.0",
|
|
53
53
|
"prettier": "^3.9.9",
|
|
54
|
+
"prettier-plugin-brace-style": "^0.10.3",
|
|
54
55
|
"sinon": "^22.1.0",
|
|
55
56
|
"strict-url-sanitise": "^0.0.1",
|
|
56
57
|
"typescript": "^7.0.2",
|
|
@@ -80,5 +81,5 @@
|
|
|
80
81
|
"engines": {
|
|
81
82
|
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
|
82
83
|
},
|
|
83
|
-
"version": "5.3.
|
|
84
|
+
"version": "5.3.4"
|
|
84
85
|
}
|
package/src/index.js
CHANGED
|
@@ -84,9 +84,11 @@ export const sanitizeURLSync = (url, opt) =>
|
|
|
84
84
|
* Sanitizes the given URL and returns its parsed components.
|
|
85
85
|
* NOTE: Blob URLs are not revoked after inspection.
|
|
86
86
|
* @param {string} url - The URL string to inspect.
|
|
87
|
+
* @param {SanitizeOptions} [opt] - The sanitization options.
|
|
87
88
|
* @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.
|
|
88
89
|
*/
|
|
89
|
-
export const inspectURL = async url
|
|
90
|
+
export const inspectURL = async (url, opt = {}) =>
|
|
91
|
+
sanitizer.inspectURL(url, opt);
|
|
90
92
|
|
|
91
93
|
/**
|
|
92
94
|
* Checks if the given string is a valid URI and is registered.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
["aaa","aaas","about","acap","acct","acd","ace","acr","adiumxtra","adt","aet","afp","afs","agtp","aim","amss","android","appdata","apt","ar","ari","ark","ars","at","attachment","aw","barion","beshare","bitcoin","bitcoincash","bl","blob","bluetooth","bolo","brid","browserext","cabal","caip","calculator","callto","cap","cast","casts","chrome","chrome-extension","cid","cm","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cttps","cvs","dab","dat","data","dav","dhttp","diaspora","dict","did","dilithium3","dis","dlna-playcontainer","dlna-playsingle","dnp","dns","dntp","doi","donau","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","esim","ethereum","example","ez","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","gcx","gdsi","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gtalk","h323","ham","hcap","hcp","hs20","http","https","hxxp","hxxps","hydrazone","hyper","i0","iax","ibi","ibi-","icap","icon","ilstring","im","imap","info","interaction","iotdisco","ipfs","ipn","ipns","ipp","ipps","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lid","linkid","lorawan","lpa","lvlt","machineProvisioningProgressReporter","magnet","mailto","maps","market","matrix","mdoc","mdoc-openid4vp","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","mqtt","mqtts","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-launchremotedesktop","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-personacard","ms-powerpoint","ms-project","ms-publisher","ms-recall","ms-remotedesktop","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-uup","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-widgetboard","ms-widgets","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mtrust","mumble","mupdate","musik","mvn","mvrp","mvrps","news","nfs","ni","nih","nntp","nostr","notes","npamp","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openid","openpgp4fpr","otpauth","palm","paparazzi","payto","pkcs11","pkg","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","rttp","sarif","secondlife","secret-token","seki","service","session","sftp","sgn","shc","shelter","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spacify","spiffe","spotify","ssb","ssh","sss","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","teamspeak","teapot","teapots","tel","teliaeid","telnet","tftp","things","thismessage","tii","tip","tn3270","tool","tttps","turn","turns","tv","udp","unreal","upn","urn","ust","ut2004","uuaid","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wasm","wasm-js","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcompute","xcon","xcon-userid","xfire","xftp","xmlrpc.beep","xmlrpc.beeps","xmpp","xrcp","xri","ymsgr","z39.50r","z39.50s","ztdnaid"]
|
|
1
|
+
["aaa","aaas","about","acap","acct","acd","ace","acr","adiumxtra","adt","aet","afp","afs","agtp","aim","alter","amss","android","appdata","apt","ar","ari","ark","ars","arv","at","attachment","aw","barion","beshare","bitcoin","bitcoincash","bl","blob","bluetooth","bolo","brid","browserext","cabal","caip","calculator","callto","canactid","cap","cast","casts","chrome","chrome-extension","cid","cm","coap","coaps","com-eventbrite-attendee","content","content-type","crid","cstr","cttps","cvs","dab","dat","data","dav","dhttp","diaspora","dict","did","dilithium3","dis","dlna-playcontainer","dlna-playsingle","dnp","dns","dntp","doi","donau","dpp","drm","dtmi","dtn","dvb","dvx","dweb","ed2k","eid","elsi","embedded","ens","esim","ethereum","example","ez","facetime","feed","feedready","fido","file","finger","first-run-pen-experience","fish","fm","ftp","fuchsia-pkg","gcx","gdsi","geo","gg","git","gitoid","gizmoproject","go","gopher","graph","gsos","gtalk","h323","ham","hcap","hcp","hs20","http","https","hxxp","hxxps","hydrazone","hyper","i0","iax","ibi","ibi-","icap","icon","ilstring","im","imap","info","interaction","iotdisco","ipfs","ipn","ipns","ipp","ipps","irc","irc6","ircs","iris","iris.beep","iris.lwz","iris.xpc","iris.xpcs","isostore","itms","jabber","jar","jms","keyparc","lastfm","lbry","ldap","ldaps","leaptofrogans","lid","linkid","locus","lorawan","lpa","lvlt","machineProvisioningProgressReporter","magnet","mailto","maps","market","matrix","mdoc","mdoc-openid4vp","message","microsoft.windows.camera","microsoft.windows.camera.multipicker","microsoft.windows.camera.picker","mid","mms","mongodb","moz","moz-extension","mqtt","mqtts","ms-access","ms-appinstaller","ms-browser-extension","ms-calculator","ms-drive-to","ms-enrollment","ms-excel","ms-eyecontrolspeech","ms-gamebarservices","ms-gamingoverlay","ms-getoffice","ms-help","ms-infopath","ms-inputapp","ms-launchremotedesktop","ms-lockscreencomponent-config","ms-media-stream-id","ms-meetnow","ms-mixedrealitycapture","ms-mobileplans","ms-newsandinterests","ms-officeapp","ms-people","ms-personacard","ms-powerpoint","ms-project","ms-publisher","ms-recall","ms-remotedesktop","ms-remotedesktop-launch","ms-restoretabcompanion","ms-screenclip","ms-screensketch","ms-search","ms-search-repair","ms-secondary-screen-controller","ms-secondary-screen-setup","ms-settings","ms-settings-airplanemode","ms-settings-bluetooth","ms-settings-camera","ms-settings-cellular","ms-settings-cloudstorage","ms-settings-connectabledevices","ms-settings-displays-topology","ms-settings-emailandaccounts","ms-settings-language","ms-settings-location","ms-settings-lock","ms-settings-nfctransactions","ms-settings-notifications","ms-settings-power","ms-settings-privacy","ms-settings-proximity","ms-settings-screenrotation","ms-settings-wifi","ms-settings-workplace","ms-spd","ms-stickers","ms-sttoverlay","ms-transit-to","ms-useractivityset","ms-uup","ms-virtualtouchpad","ms-visio","ms-walk-to","ms-whiteboard","ms-whiteboard-cmd","ms-widgetboard","ms-widgets","ms-word","msnim","msrp","msrps","mss","mt","mtqp","mtrust","mumble","mupdate","musik","mvn","mvrp","mvrps","news","nfs","ni","nih","nntp","nostr","notes","npamp","num","ocf","oid","onenote","onenote-cmd","opaquelocktoken","openid","openpgp4fpr","otpauth","palm","paparazzi","payto","pkcs11","pkg","platform","pop","pres","proxy","psyc","pttp","pwid","qb","query","quic-transport","redis","rediss","reload","res","resource","rmi","rsync","rtmfp","rtmp","rtsp","rtsps","rtspu","rttp","sarif","secondlife","secret-token","seki","service","session","sftp","sgn","shc","shelter","sieve","simpleledger","simplex","sip","sips","skype","smb","smp","sms","smtp","snmp","soap.beep","soap.beeps","soldat","spacify","spiffe","spotify","ssb","ssh","sss","starknet","steam","stun","stuns","submit","svn","swh","swid","swidpath","tag","taler","tcxp","teamspeak","teapot","teapots","tel","teliaeid","telnet","tftp","things","thismessage","tii","tip","tn3270","tool","tttps","turn","turns","tv","udp","unreal","upn","urn","ust","ut2004","uuaid","uuid-in-package","v-event","vemmi","ventrilo","ves","view-source","vnc","vscode","vscode-insiders","vsls","w3","wasm","wasm-js","wcr","web3","webcal","wifi","ws","wss","wtai","wyciwyg","xcompute","xcon","xcon-userid","xfire","xftp","xmlrpc.beep","xmlrpc.beeps","xmpp","xrcp","xri","ymsgr","z39.50r","z39.50s","ztdnaid"]
|
package/src/mjs/sanitize.js
CHANGED
|
@@ -118,9 +118,10 @@ export class URLSanitizer extends URISchemes {
|
|
|
118
118
|
* Inspects, parses, and sanitizes the given URL.
|
|
119
119
|
* @private
|
|
120
120
|
* @param {string} url - The URL string to parse.
|
|
121
|
+
* @param {InternalSanitizeOptions} options - Sanitization options.
|
|
121
122
|
* @returns {InspectedURLResult} The result of an inspected URL.
|
|
122
123
|
*/
|
|
123
|
-
#inspect(url) {
|
|
124
|
+
#inspect(url, options) {
|
|
124
125
|
const inspectedURL = {
|
|
125
126
|
input: url,
|
|
126
127
|
href: null,
|
|
@@ -137,12 +138,7 @@ export class URLSanitizer extends URISchemes {
|
|
|
137
138
|
let sanitizedURL;
|
|
138
139
|
let invalidReason = null;
|
|
139
140
|
try {
|
|
140
|
-
sanitizedURL = this.#filter.sanitize(url,
|
|
141
|
-
...this.#defaultOpts,
|
|
142
|
-
allow: ['data'],
|
|
143
|
-
allowRelative: true,
|
|
144
|
-
schemes: this.#allowedSchemes
|
|
145
|
-
});
|
|
141
|
+
sanitizedURL = this.#filter.sanitize(url, options);
|
|
146
142
|
if (!sanitizedURL) {
|
|
147
143
|
invalidReason =
|
|
148
144
|
'Sanitization failed (blocked by allowed schemes or rules).';
|
|
@@ -227,6 +223,23 @@ export class URLSanitizer extends URISchemes {
|
|
|
227
223
|
}
|
|
228
224
|
}
|
|
229
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Re-throws errors or operation aborts.
|
|
228
|
+
* @private
|
|
229
|
+
* @param {Error} e - The error object to evaluate.
|
|
230
|
+
* @param {InternalSanitizeOptions} options - The internal sanitization options.
|
|
231
|
+
* @throws {Error} Re-throws the given error if it is a TypeError, AbortError, or aborted signal.
|
|
232
|
+
*/
|
|
233
|
+
#shouldThrow(e, options) {
|
|
234
|
+
if (
|
|
235
|
+
e instanceof TypeError ||
|
|
236
|
+
e.name === 'AbortError' ||
|
|
237
|
+
options.signal?.aborted
|
|
238
|
+
) {
|
|
239
|
+
throw e;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
230
243
|
/**
|
|
231
244
|
* Gets the list of registered URI schemes.
|
|
232
245
|
* @returns {string[]} An array of registered schemes.
|
|
@@ -349,16 +362,31 @@ export class URLSanitizer extends URISchemes {
|
|
|
349
362
|
);
|
|
350
363
|
}
|
|
351
364
|
}
|
|
365
|
+
} catch (e) {
|
|
366
|
+
this.#shouldThrow(e, options);
|
|
367
|
+
if (options.debug) {
|
|
368
|
+
logDebug(`Failed to sanitize URL: ${truncateURL(url)}`, e);
|
|
369
|
+
}
|
|
370
|
+
return null;
|
|
352
371
|
} finally {
|
|
353
372
|
if (options.revokeObjectURL) {
|
|
354
373
|
URL.revokeObjectURL(url);
|
|
355
374
|
}
|
|
356
375
|
}
|
|
357
376
|
return sanitizedData;
|
|
358
|
-
} else if (scheme === 'data') {
|
|
359
|
-
return this.#filter.sanitizeDataURL(url, options);
|
|
360
377
|
}
|
|
361
|
-
|
|
378
|
+
try {
|
|
379
|
+
if (scheme === 'data') {
|
|
380
|
+
return this.#filter.sanitizeDataURL(url, options);
|
|
381
|
+
}
|
|
382
|
+
return this.#filter.sanitize(url, options);
|
|
383
|
+
} catch (e) {
|
|
384
|
+
this.#shouldThrow(e, options);
|
|
385
|
+
if (options.debug) {
|
|
386
|
+
logDebug(`Failed to sanitize URL: ${truncateURL(url)}`, e);
|
|
387
|
+
}
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
362
390
|
}
|
|
363
391
|
|
|
364
392
|
/**
|
|
@@ -380,7 +408,15 @@ export class URLSanitizer extends URISchemes {
|
|
|
380
408
|
}
|
|
381
409
|
return null;
|
|
382
410
|
}
|
|
383
|
-
|
|
411
|
+
try {
|
|
412
|
+
return this.#filter.sanitize(url, options);
|
|
413
|
+
} catch (e) {
|
|
414
|
+
this.#shouldThrow(e, options);
|
|
415
|
+
if (options.debug) {
|
|
416
|
+
logDebug(`Failed to sanitize URL: ${truncateURL(url)}`, e);
|
|
417
|
+
}
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
384
420
|
}
|
|
385
421
|
|
|
386
422
|
/**
|
|
@@ -389,7 +425,7 @@ export class URLSanitizer extends URISchemes {
|
|
|
389
425
|
* @param {SanitizeOptions} [opt] - The sanitization options.
|
|
390
426
|
* @returns {Promise<InspectedURLResult>} A promise resolving to the inspected URL result.
|
|
391
427
|
*/
|
|
392
|
-
async inspectURL(url, opt) {
|
|
428
|
+
async inspectURL(url, opt = {}) {
|
|
393
429
|
const { options, scheme } = this.#normalizeOptions(url, opt);
|
|
394
430
|
if (scheme === 'blob') {
|
|
395
431
|
return this.#inspectBlob(url, options);
|
package/src/mjs/utility.js
CHANGED
|
@@ -356,6 +356,8 @@ export const encodeBufferToBase64 = buffer => {
|
|
|
356
356
|
* @param {AbortSignal} [signal] - The abort signal.
|
|
357
357
|
* @returns {Promise<ArrayBuffer>} A promise resolving to the generated ArrayBuffer.
|
|
358
358
|
*/
|
|
359
|
+
// Stream reading requires sequential async execution.
|
|
360
|
+
/* eslint-disable no-await-in-loop */
|
|
359
361
|
export const readStreamInChunksAsArrayBuffer = async (
|
|
360
362
|
response,
|
|
361
363
|
maxSize,
|
|
@@ -409,6 +411,7 @@ export const readStreamInChunksAsArrayBuffer = async (
|
|
|
409
411
|
reader.releaseLock();
|
|
410
412
|
}
|
|
411
413
|
};
|
|
414
|
+
/* eslint-enable no-await-in-loop */
|
|
412
415
|
|
|
413
416
|
/**
|
|
414
417
|
* Fetches a Blob URL and extracts its ArrayBuffer and MIME type.
|
package/types/index.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export { URLSanitizer };
|
|
|
44
44
|
declare const sanitizer: URLSanitizer;
|
|
45
45
|
export declare const sanitizeURL: (url: string, opt?: SanitizeOptions) => Promise<string | null>;
|
|
46
46
|
export declare const sanitizeURLSync: (url: string, opt?: SanitizeOptions) => string | null;
|
|
47
|
-
export declare const inspectURL: (url: string) => Promise<InspectedURLResult>;
|
|
47
|
+
export declare const inspectURL: (url: string, opt?: SanitizeOptions) => Promise<InspectedURLResult>;
|
|
48
48
|
export declare const isValidURI: (uri: string) => boolean;
|
|
49
49
|
export declare const isURISync: (uri: string) => boolean;
|
|
50
50
|
export default sanitizer;
|
package/types/mjs/filter.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare class SanitizeContext {
|
|
|
12
12
|
schemeMap: Map<string, boolean>;
|
|
13
13
|
allowRelative: boolean | undefined;
|
|
14
14
|
debug: boolean | undefined;
|
|
15
|
+
schemes: Set<string> | undefined;
|
|
15
16
|
constructor(domPurifyInstance: DOMPurify, opt?: InternalSanitizeOptions);
|
|
16
17
|
private #compileRules;
|
|
17
18
|
private #registerScheme;
|
package/types/mjs/sanitize.d.ts
CHANGED