@eggjs/security 5.0.0-beta.35 → 5.0.0-beta.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.
- package/dist/agent.d.ts +9 -5
- package/dist/agent.js +14 -10
- package/dist/app/extend/agent.d.ts +8 -4
- package/dist/app/extend/agent.js +12 -8
- package/dist/app/extend/application.d.ts +11 -7
- package/dist/app/extend/application.js +32 -32
- package/dist/app/extend/context.d.ts +55 -51
- package/dist/app/extend/context.js +185 -240
- package/dist/app/extend/helper.d.ts +5 -2
- package/dist/app/extend/helper.js +8 -6
- package/dist/app/extend/response.d.ts +38 -34
- package/dist/app/extend/response.js +69 -82
- package/dist/app/middleware/securities.d.ts +5 -2
- package/dist/app/middleware/securities.js +38 -52
- package/dist/app.d.ts +9 -5
- package/dist/app.js +23 -25
- package/dist/config/config.default.d.ts +34 -45
- package/dist/config/config.default.js +158 -362
- package/dist/config/config.local.d.ts +6 -3
- package/dist/config/config.local.js +6 -8
- package/dist/index.d.ts +20 -16
- package/dist/index.js +24 -21
- package/dist/lib/extend/safe_curl.d.ts +16 -13
- package/dist/lib/extend/safe_curl.js +17 -23
- package/dist/lib/helper/cliFilter.d.ts +4 -4
- package/dist/lib/helper/cliFilter.js +16 -15
- package/dist/lib/helper/escape.d.ts +2 -2
- package/dist/lib/helper/escape.js +7 -3
- package/dist/lib/helper/escapeShellArg.d.ts +4 -1
- package/dist/lib/helper/escapeShellArg.js +6 -4
- package/dist/lib/helper/escapeShellCmd.d.ts +4 -1
- package/dist/lib/helper/escapeShellCmd.js +14 -13
- package/dist/lib/helper/index.d.ts +22 -19
- package/dist/lib/helper/index.js +19 -15
- package/dist/lib/helper/shtml.d.ts +6 -2
- package/dist/lib/helper/shtml.js +52 -68
- package/dist/lib/helper/sjs.d.ts +4 -4
- package/dist/lib/helper/sjs.js +31 -44
- package/dist/lib/helper/sjson.d.ts +4 -1
- package/dist/lib/helper/sjson.js +28 -35
- package/dist/lib/helper/spath.d.ts +7 -5
- package/dist/lib/helper/spath.js +15 -24
- package/dist/lib/helper/surl.d.ts +6 -2
- package/dist/lib/helper/surl.js +22 -27
- package/dist/lib/middlewares/csp.d.ts +6 -3
- package/dist/lib/middlewares/csp.js +43 -54
- package/dist/lib/middlewares/csrf.d.ts +6 -3
- package/dist/lib/middlewares/csrf.js +31 -35
- package/dist/lib/middlewares/dta.d.ts +5 -2
- package/dist/lib/middlewares/dta.js +11 -10
- package/dist/lib/middlewares/hsts.d.ts +6 -3
- package/dist/lib/middlewares/hsts.js +17 -19
- package/dist/lib/middlewares/index.d.ts +24 -21
- package/dist/lib/middlewares/index.js +26 -22
- package/dist/lib/middlewares/methodnoallow.d.ts +5 -2
- package/dist/lib/middlewares/methodnoallow.js +13 -18
- package/dist/lib/middlewares/noopen.d.ts +6 -3
- package/dist/lib/middlewares/noopen.js +14 -13
- package/dist/lib/middlewares/nosniff.d.ts +6 -3
- package/dist/lib/middlewares/nosniff.js +22 -24
- package/dist/lib/middlewares/referrerPolicy.d.ts +6 -3
- package/dist/lib/middlewares/referrerPolicy.js +27 -30
- package/dist/lib/middlewares/xframe.d.ts +6 -3
- package/dist/lib/middlewares/xframe.js +16 -15
- package/dist/lib/middlewares/xssProtection.d.ts +6 -3
- package/dist/lib/middlewares/xssProtection.js +15 -12
- package/dist/lib/utils.d.ts +22 -17
- package/dist/lib/utils.js +112 -177
- package/dist/types.d.ts +38 -36
- package/dist/types.js +1 -2
- package/package.json +31 -37
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import { checkIfIgnore } from "../utils.js";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
|
|
3
|
+
//#region src/lib/middlewares/nosniff.ts
|
|
4
4
|
const RedirectStatus = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
300: true,
|
|
6
|
+
301: true,
|
|
7
|
+
302: true,
|
|
8
|
+
303: true,
|
|
9
|
+
305: true,
|
|
10
|
+
307: true,
|
|
11
|
+
308: true
|
|
12
12
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (checkIfIgnore(opts, ctx))
|
|
24
|
-
return;
|
|
25
|
-
ctx.set('x-content-type-options', 'nosniff');
|
|
26
|
-
};
|
|
13
|
+
var nosniff_default = (options) => {
|
|
14
|
+
return async function nosniff(ctx, next) {
|
|
15
|
+
await next();
|
|
16
|
+
if (RedirectStatus[ctx.status]) return;
|
|
17
|
+
if (checkIfIgnore({
|
|
18
|
+
...options,
|
|
19
|
+
...ctx.securityOptions.nosniff
|
|
20
|
+
}, ctx)) return;
|
|
21
|
+
ctx.set("x-content-type-options", "nosniff");
|
|
22
|
+
};
|
|
27
23
|
};
|
|
28
|
-
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { nosniff_default as default };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { SecurityConfig } from "../../config/config.default.js";
|
|
2
|
+
import { MiddlewareFunc } from "egg";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/middlewares/referrerPolicy.d.ts
|
|
3
5
|
declare const _default: (options: SecurityConfig["referrerPolicy"]) => MiddlewareFunc;
|
|
4
|
-
|
|
6
|
+
//#endregion
|
|
7
|
+
export { _default as default };
|
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
import { checkIfIgnore } from "../utils.js";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
//#region src/lib/middlewares/referrerPolicy.ts
|
|
3
4
|
const ALLOWED_POLICIES_ENUM = [
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
"no-referrer",
|
|
6
|
+
"no-referrer-when-downgrade",
|
|
7
|
+
"origin",
|
|
8
|
+
"origin-when-cross-origin",
|
|
9
|
+
"same-origin",
|
|
10
|
+
"strict-origin",
|
|
11
|
+
"strict-origin-when-cross-origin",
|
|
12
|
+
"unsafe-url",
|
|
13
|
+
""
|
|
13
14
|
];
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const policy = opts.value;
|
|
28
|
-
if (!ALLOWED_POLICIES_ENUM.includes(policy)) {
|
|
29
|
-
throw new Error(`"${policy}" is not available.`);
|
|
30
|
-
}
|
|
31
|
-
ctx.set('referrer-policy', policy);
|
|
32
|
-
};
|
|
15
|
+
var referrerPolicy_default = (options) => {
|
|
16
|
+
return async function referrerPolicy(ctx, next) {
|
|
17
|
+
await next();
|
|
18
|
+
const opts = {
|
|
19
|
+
...options,
|
|
20
|
+
...ctx.securityOptions.refererPolicy,
|
|
21
|
+
...ctx.securityOptions.referrerPolicy
|
|
22
|
+
};
|
|
23
|
+
if (checkIfIgnore(opts, ctx)) return;
|
|
24
|
+
const policy = opts.value;
|
|
25
|
+
if (!ALLOWED_POLICIES_ENUM.includes(policy)) throw new Error(`"${policy}" is not available.`);
|
|
26
|
+
ctx.set("referrer-policy", policy);
|
|
27
|
+
};
|
|
33
28
|
};
|
|
34
|
-
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { referrerPolicy_default as default };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { SecurityConfig } from "../../config/config.default.js";
|
|
2
|
+
import { MiddlewareFunc } from "egg";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/middlewares/xframe.d.ts
|
|
3
5
|
declare const _default: (options: SecurityConfig["xframe"]) => MiddlewareFunc;
|
|
4
|
-
|
|
6
|
+
//#endregion
|
|
7
|
+
export { _default as default };
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { checkIfIgnore } from "../utils.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
2
|
+
|
|
3
|
+
//#region src/lib/middlewares/xframe.ts
|
|
4
|
+
var xframe_default = (options) => {
|
|
5
|
+
return async function xframe(ctx, next) {
|
|
6
|
+
await next();
|
|
7
|
+
const opts = {
|
|
8
|
+
...options,
|
|
9
|
+
...ctx.securityOptions.xframe
|
|
10
|
+
};
|
|
11
|
+
if (checkIfIgnore(opts, ctx)) return;
|
|
12
|
+
const value = opts.value || "SAMEORIGIN";
|
|
13
|
+
ctx.set("x-frame-options", value);
|
|
14
|
+
};
|
|
16
15
|
};
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { xframe_default as default };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { SecurityConfig } from "../../config/config.default.js";
|
|
2
|
+
import { MiddlewareFunc } from "egg";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/middlewares/xssProtection.d.ts
|
|
3
5
|
declare const _default: (options: SecurityConfig["xssProtection"]) => MiddlewareFunc;
|
|
4
|
-
|
|
6
|
+
//#endregion
|
|
7
|
+
export { _default as default };
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { checkIfIgnore } from "../utils.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
|
|
3
|
+
//#region src/lib/middlewares/xssProtection.ts
|
|
4
|
+
var xssProtection_default = (options) => {
|
|
5
|
+
return async function xssProtection(ctx, next) {
|
|
6
|
+
await next();
|
|
7
|
+
const opts = {
|
|
8
|
+
...options,
|
|
9
|
+
...ctx.securityOptions.xssProtection
|
|
10
|
+
};
|
|
11
|
+
if (checkIfIgnore(opts, ctx)) return;
|
|
12
|
+
ctx.set("x-xss-protection", opts.value);
|
|
13
|
+
};
|
|
13
14
|
};
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { xssProtection_default as default };
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { SecurityConfig } from "../config/config.default.js";
|
|
2
|
+
import { Context } from "egg";
|
|
3
|
+
import { PathMatchingFun } from "@eggjs/path-matching";
|
|
4
|
+
|
|
5
|
+
//#region src/lib/utils.d.ts
|
|
6
|
+
|
|
4
7
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
* Check whether a domain is in the safe domain white list or not.
|
|
9
|
+
* @param {String} domain The inputted domain.
|
|
10
|
+
* @param {Array<string>} whiteList The white list for domain.
|
|
11
|
+
* @return {Boolean} If the `domain` is in the white list, return true; otherwise false.
|
|
12
|
+
*/
|
|
13
|
+
declare function isSafeDomain(domain: string, whiteList: string[]): boolean;
|
|
14
|
+
declare function isSafePath(path: string, ctx: Context): boolean;
|
|
15
|
+
declare function checkIfIgnore(opts: {
|
|
16
|
+
enable: boolean;
|
|
17
|
+
matching?: PathMatchingFun;
|
|
15
18
|
}, ctx: Context): boolean;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
declare function getCookieDomain(hostname: string): string;
|
|
20
|
+
declare function merge(origin: Record<string, any>, opts?: Record<string, any>): Record<string, any>;
|
|
21
|
+
declare function preprocessConfig(config: SecurityConfig): void;
|
|
22
|
+
declare function getFromUrl(url: string, prop: string): string | null;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { checkIfIgnore, getCookieDomain, getFromUrl, isSafeDomain, isSafePath, merge, preprocessConfig };
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,192 +1,127 @@
|
|
|
1
|
-
import { normalize } from
|
|
2
|
-
import IP from
|
|
3
|
-
import matcher from
|
|
1
|
+
import { normalize } from "node:path";
|
|
2
|
+
import IP from "@eggjs/ip";
|
|
3
|
+
import matcher from "matcher";
|
|
4
|
+
|
|
5
|
+
//#region src/lib/utils.ts
|
|
4
6
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (rule.includes('*')) {
|
|
21
|
-
return matcher.isMatch(domain, rule);
|
|
22
|
-
}
|
|
23
|
-
// If domain is an absolute path such as `http://...`
|
|
24
|
-
// We can directly check whether it directly equals to `domain`
|
|
25
|
-
// And we don't need to cope with `endWith`.
|
|
26
|
-
if (domain === rule)
|
|
27
|
-
return true;
|
|
28
|
-
// ensure wwweggjs.com not match eggjs.com
|
|
29
|
-
if (!rule.startsWith('.'))
|
|
30
|
-
rule = `.${rule}`;
|
|
31
|
-
return hostname.endsWith(rule);
|
|
32
|
-
});
|
|
7
|
+
* Check whether a domain is in the safe domain white list or not.
|
|
8
|
+
* @param {String} domain The inputted domain.
|
|
9
|
+
* @param {Array<string>} whiteList The white list for domain.
|
|
10
|
+
* @return {Boolean} If the `domain` is in the white list, return true; otherwise false.
|
|
11
|
+
*/
|
|
12
|
+
function isSafeDomain(domain, whiteList) {
|
|
13
|
+
if (typeof domain !== "string") return false;
|
|
14
|
+
domain = domain.toLowerCase();
|
|
15
|
+
const hostname = "." + domain;
|
|
16
|
+
return whiteList.some((rule) => {
|
|
17
|
+
if (rule.includes("*")) return matcher.isMatch(domain, rule);
|
|
18
|
+
if (domain === rule) return true;
|
|
19
|
+
if (!rule.startsWith(".")) rule = `.${rule}`;
|
|
20
|
+
return hostname.endsWith(rule);
|
|
21
|
+
});
|
|
33
22
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
ctx.coreLogger.warn('[@eggjs/security: dta global block] : decode file path %j failed.', path);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const normalizePath = normalize(path);
|
|
48
|
-
return !(normalizePath.startsWith('../') || normalizePath.startsWith('..\\'));
|
|
23
|
+
function isSafePath(path, ctx) {
|
|
24
|
+
path = "." + path;
|
|
25
|
+
if (path.includes("%")) try {
|
|
26
|
+
path = decodeURIComponent(path);
|
|
27
|
+
} catch {
|
|
28
|
+
if (ctx.app.config.env === "local" || ctx.app.config.env === "unittest") ctx.coreLogger.warn("[@eggjs/security: dta global block] : decode file path %j failed.", path);
|
|
29
|
+
}
|
|
30
|
+
const normalizePath = normalize(path);
|
|
31
|
+
return !(normalizePath.startsWith("../") || normalizePath.startsWith("..\\"));
|
|
49
32
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return true;
|
|
54
|
-
return !opts.matching?.(ctx);
|
|
33
|
+
function checkIfIgnore(opts, ctx) {
|
|
34
|
+
if (!opts.enable) return true;
|
|
35
|
+
return !opts.matching?.(ctx);
|
|
55
36
|
}
|
|
56
37
|
const IP_RE = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
57
38
|
const topDomains = {};
|
|
58
|
-
[
|
|
59
|
-
|
|
39
|
+
[
|
|
40
|
+
".net.cn",
|
|
41
|
+
".gov.cn",
|
|
42
|
+
".org.cn",
|
|
43
|
+
".com.cn"
|
|
44
|
+
].forEach((item) => {
|
|
45
|
+
topDomains[item] = 2 - item.split(".").length;
|
|
60
46
|
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// domain=.domain.com;
|
|
70
|
-
const splits = hostname.split('.');
|
|
71
|
-
let index = -2;
|
|
72
|
-
// only when `*.test.*.com` set `.test.*.com`
|
|
73
|
-
if (splits.length >= 4 && splits[splits.length - 3] === 'test') {
|
|
74
|
-
index = -3;
|
|
75
|
-
}
|
|
76
|
-
let domain = getDomain(splits, index);
|
|
77
|
-
if (topDomains[domain]) {
|
|
78
|
-
// app.foo.org.cn => .foo.org.cn
|
|
79
|
-
domain = getDomain(splits, index + topDomains[domain]);
|
|
80
|
-
}
|
|
81
|
-
return domain;
|
|
47
|
+
function getCookieDomain(hostname) {
|
|
48
|
+
if (IP_RE.test(hostname)) return hostname;
|
|
49
|
+
const splits = hostname.split(".");
|
|
50
|
+
let index = -2;
|
|
51
|
+
if (splits.length >= 4 && splits[splits.length - 3] === "test") index = -3;
|
|
52
|
+
let domain = getDomain(splits, index);
|
|
53
|
+
if (topDomains[domain]) domain = getDomain(splits, index + topDomains[domain]);
|
|
54
|
+
return domain;
|
|
82
55
|
}
|
|
83
56
|
function getDomain(splits, index) {
|
|
84
|
-
|
|
57
|
+
return "." + splits.slice(index).join(".");
|
|
85
58
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
return res;
|
|
59
|
+
function merge(origin, opts) {
|
|
60
|
+
if (!opts) return origin;
|
|
61
|
+
const res = {};
|
|
62
|
+
const originKeys = Object.keys(origin);
|
|
63
|
+
for (let i = 0; i < originKeys.length; i++) {
|
|
64
|
+
const key = originKeys[i];
|
|
65
|
+
res[key] = origin[key];
|
|
66
|
+
}
|
|
67
|
+
const keys = Object.keys(opts);
|
|
68
|
+
for (let i = 0; i < keys.length; i++) {
|
|
69
|
+
const key = keys[i];
|
|
70
|
+
res[key] = opts[key];
|
|
71
|
+
}
|
|
72
|
+
return res;
|
|
102
73
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (exception(address)) {
|
|
142
|
-
return true;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// check black list
|
|
146
|
-
for (const contains of blackList) {
|
|
147
|
-
if (contains(address)) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// default allow
|
|
153
|
-
return true;
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
// Make sure that `whiteList` or `protocolWhiteList` is case insensitive
|
|
157
|
-
config.domainWhiteList = config.domainWhiteList || [];
|
|
158
|
-
config.domainWhiteList = config.domainWhiteList.map((domain) => domain.toLowerCase());
|
|
159
|
-
config.protocolWhiteList = config.protocolWhiteList || [];
|
|
160
|
-
config.protocolWhiteList = config.protocolWhiteList.map((protocol) => protocol.toLowerCase());
|
|
161
|
-
// Make sure refererWhiteList is case insensitive
|
|
162
|
-
if (config.csrf && config.csrf.refererWhiteList) {
|
|
163
|
-
config.csrf.refererWhiteList = config.csrf.refererWhiteList.map((ref) => ref.toLowerCase());
|
|
164
|
-
}
|
|
165
|
-
// Directly converted to Set collection by a private property (not documented),
|
|
166
|
-
// And we NO LONGER need to do conversion in `foreach` again and again in `lib/helper/surl.ts`.
|
|
167
|
-
const protocolWhiteListSet = new Set(config.protocolWhiteList);
|
|
168
|
-
protocolWhiteListSet.add('http');
|
|
169
|
-
protocolWhiteListSet.add('https');
|
|
170
|
-
protocolWhiteListSet.add('file');
|
|
171
|
-
protocolWhiteListSet.add('data');
|
|
172
|
-
Object.defineProperty(config, '__protocolWhiteListSet', {
|
|
173
|
-
value: protocolWhiteListSet,
|
|
174
|
-
enumerable: false,
|
|
175
|
-
});
|
|
74
|
+
function preprocessConfig(config) {
|
|
75
|
+
const ssrf = config.ssrf;
|
|
76
|
+
if (ssrf && ssrf.ipBlackList && !ssrf.checkAddress) {
|
|
77
|
+
const blackList = ssrf.ipBlackList.map(getContains);
|
|
78
|
+
const exceptionList = (ssrf.ipExceptionList || []).map(getContains);
|
|
79
|
+
const hostnameExceptionList = ssrf.hostnameExceptionList;
|
|
80
|
+
ssrf.checkAddress = (ipAddresses, _family, hostname) => {
|
|
81
|
+
if (hostname && hostnameExceptionList) {
|
|
82
|
+
if (hostnameExceptionList.includes(hostname)) return true;
|
|
83
|
+
}
|
|
84
|
+
if (!Array.isArray(ipAddresses)) ipAddresses = [ipAddresses];
|
|
85
|
+
for (const ipAddress of ipAddresses) {
|
|
86
|
+
let address;
|
|
87
|
+
if (typeof ipAddress === "string") address = ipAddress;
|
|
88
|
+
else {
|
|
89
|
+
if (ipAddress.family === 6) continue;
|
|
90
|
+
address = ipAddress.address;
|
|
91
|
+
}
|
|
92
|
+
for (const exception of exceptionList) if (exception(address)) return true;
|
|
93
|
+
for (const contains of blackList) if (contains(address)) return false;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
config.domainWhiteList = config.domainWhiteList || [];
|
|
99
|
+
config.domainWhiteList = config.domainWhiteList.map((domain) => domain.toLowerCase());
|
|
100
|
+
config.protocolWhiteList = config.protocolWhiteList || [];
|
|
101
|
+
config.protocolWhiteList = config.protocolWhiteList.map((protocol) => protocol.toLowerCase());
|
|
102
|
+
if (config.csrf && config.csrf.refererWhiteList) config.csrf.refererWhiteList = config.csrf.refererWhiteList.map((ref) => ref.toLowerCase());
|
|
103
|
+
const protocolWhiteListSet = new Set(config.protocolWhiteList);
|
|
104
|
+
protocolWhiteListSet.add("http");
|
|
105
|
+
protocolWhiteListSet.add("https");
|
|
106
|
+
protocolWhiteListSet.add("file");
|
|
107
|
+
protocolWhiteListSet.add("data");
|
|
108
|
+
Object.defineProperty(config, "__protocolWhiteListSet", {
|
|
109
|
+
value: protocolWhiteListSet,
|
|
110
|
+
enumerable: false
|
|
111
|
+
});
|
|
176
112
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
113
|
+
function getFromUrl(url, prop) {
|
|
114
|
+
try {
|
|
115
|
+
const parsed = new URL(url);
|
|
116
|
+
return Reflect.get(parsed, prop);
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
185
120
|
}
|
|
186
121
|
function getContains(ip) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
return IP.cidrSubnet(ip).contains;
|
|
122
|
+
if (IP.isV4Format(ip) || IP.isV6Format(ip)) return (address) => address === ip;
|
|
123
|
+
return IP.cidrSubnet(ip).contains;
|
|
191
124
|
}
|
|
192
|
-
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
export { checkIfIgnore, getCookieDomain, getFromUrl, isSafeDomain, isSafePath, merge, preprocessConfig };
|