UNPKG

2.58 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var FILE_URI_MATCH = /\/\/\//;
4var INVALID_RELATIVE_URL = /[/\\][/\\]/;
5var VALID_PROTOCOLS = ['https:', 'http:'];
6var DUMMY_HOSTNAME = 'http://test.com';
7function isSafe(redirectUrl, _a) {
8 var _b = _a === void 0 ? {} : _a, _c = _b.whitelist, whitelist = _c === void 0 ? [] : _c, _d = _b.subdomains, subdomains = _d === void 0 ? [] : _d, matchPath = _b.matchPath, requireAbsolute = _b.requireAbsolute, requireSSL = _b.requireSSL;
9 if (FILE_URI_MATCH.test(redirectUrl)) {
10 return false;
11 }
12 if (redirectUrl.startsWith('/')) {
13 if (whitelist.length > 0 || subdomains.length > 0 || requireAbsolute || requireSSL) {
14 return false;
15 }
16 if (matchPath) {
17 // Creating a new URL expands the pathname in case of things like `/a/../b`
18 return pathMatches(new URL(redirectUrl, DUMMY_HOSTNAME), redirectUrl, matchPath);
19 }
20 return !INVALID_RELATIVE_URL.test(redirectUrl);
21 }
22 var url;
23 try {
24 url = new URL(redirectUrl);
25 }
26 catch (error) {
27 return false;
28 }
29 if (!VALID_PROTOCOLS.includes(url.protocol)) {
30 return false;
31 }
32 if (requireSSL && url.protocol !== 'https:') {
33 return false;
34 }
35 if (url.username || url.password) {
36 return false;
37 }
38 if (matchPath && !pathMatches(url, redirectUrl, matchPath)) {
39 return false;
40 }
41 if (!hostIsValid(url, whitelist, subdomains)) {
42 return false;
43 }
44 return true;
45}
46exports.isSafe = isSafe;
47function hostIsValid(url, whitelist, subdomains) {
48 if (!subdomains.every(function (subdomain) { return subdomain.startsWith('.'); })) {
49 throw new TypeError('Subdomains must begin with .');
50 }
51 var hostname = url.hostname;
52 return ((whitelist.length === 0 && subdomains.length === 0) ||
53 whitelist.includes(hostname) ||
54 subdomains.some(function (subdomain) { return hostname.endsWith(subdomain); }));
55}
56function pathMatches(url, originalUrl, matcher) {
57 var pathname = url.pathname;
58 // Gets just the unresolve pathname, i.e., `http://foo.com/a/../b => /a/../b
59 var originalPathname = originalUrl.replace(url.origin, '').split('?')[0];
60 return typeof matcher === 'string'
61 ? pathname === matcher && originalPathname === matcher
62 : matcher.test(pathname) && matcher.test(originalPathname);
63}
64function makeSafe(url, fallback, options) {
65 return isSafe(url, options) ? encodeURI(url) : fallback;
66}
67exports.makeSafe = makeSafe;