@eggjs/security 5.0.0-beta.20 → 5.0.0-beta.22
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 +5 -9
- package/dist/agent.js +11 -15
- package/dist/app/extend/agent.d.ts +4 -9
- package/dist/app/extend/agent.js +8 -12
- package/dist/app/extend/application.d.ts +8 -4
- package/dist/app/extend/application.js +32 -4
- package/dist/app/extend/context.d.ts +58 -4
- package/dist/app/extend/context.js +244 -4
- package/dist/app/extend/helper.d.ts +10 -22
- package/dist/app/extend/helper.js +5 -17
- package/dist/app/extend/response.d.ts +35 -4
- package/dist/app/extend/response.js +83 -5
- package/dist/app/middleware/securities.d.ts +4 -8
- package/dist/app/middleware/securities.js +52 -49
- package/dist/app.d.ts +5 -9
- package/dist/app.js +26 -24
- package/dist/config/config.default.d.ts +867 -2
- package/dist/config/config.default.js +366 -3
- package/dist/config/config.local.d.ts +2 -5
- package/dist/config/config.local.js +8 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +5 -8
- package/dist/lib/extend/safe_curl.d.ts +16 -3
- package/dist/lib/extend/safe_curl.js +25 -3
- package/dist/lib/helper/cliFilter.d.ts +4 -2
- package/dist/lib/helper/cliFilter.js +17 -3
- package/dist/lib/helper/escape.d.ts +2 -2
- package/dist/lib/helper/escape.js +3 -3
- package/dist/lib/helper/escapeShellArg.d.ts +1 -2
- package/dist/lib/helper/escapeShellArg.js +5 -3
- package/dist/lib/helper/escapeShellCmd.d.ts +1 -2
- package/dist/lib/helper/escapeShellCmd.js +14 -3
- package/dist/lib/helper/index.d.ts +19 -22
- package/dist/lib/helper/index.js +21 -13
- package/dist/lib/helper/shtml.d.ts +2 -2
- package/dist/lib/helper/shtml.js +69 -4
- package/dist/lib/helper/sjs.d.ts +4 -2
- package/dist/lib/helper/sjs.js +49 -3
- package/dist/lib/helper/sjson.d.ts +1 -2
- package/dist/lib/helper/sjson.js +39 -4
- package/dist/lib/helper/spath.d.ts +5 -2
- package/dist/lib/helper/spath.js +25 -3
- package/dist/lib/helper/surl.d.ts +2 -2
- package/dist/lib/helper/surl.js +30 -3
- package/dist/lib/middlewares/csp.d.ts +3 -6
- package/dist/lib/middlewares/csp.js +57 -4
- package/dist/lib/middlewares/csrf.d.ts +3 -6
- package/dist/lib/middlewares/csrf.js +37 -4
- package/dist/lib/middlewares/dta.d.ts +2 -5
- package/dist/lib/middlewares/dta.js +12 -4
- package/dist/lib/middlewares/hsts.d.ts +3 -6
- package/dist/lib/middlewares/hsts.js +21 -4
- package/dist/lib/middlewares/index.d.ts +11 -16
- package/dist/lib/middlewares/index.js +23 -14
- package/dist/lib/middlewares/methodnoallow.d.ts +2 -5
- package/dist/lib/middlewares/methodnoallow.js +20 -3
- package/dist/lib/middlewares/noopen.d.ts +3 -6
- package/dist/lib/middlewares/noopen.js +15 -4
- package/dist/lib/middlewares/nosniff.d.ts +3 -6
- package/dist/lib/middlewares/nosniff.js +28 -4
- package/dist/lib/middlewares/referrerPolicy.d.ts +3 -6
- package/dist/lib/middlewares/referrerPolicy.js +35 -4
- package/dist/lib/middlewares/xframe.d.ts +3 -6
- package/dist/lib/middlewares/xframe.js +17 -4
- package/dist/lib/middlewares/xssProtection.d.ts +3 -6
- package/dist/lib/middlewares/xssProtection.js +14 -4
- package/dist/lib/utils.d.ts +12 -17
- package/dist/lib/utils.js +192 -3
- package/dist/types.d.ts +36 -3
- package/dist/types.js +2 -3
- package/package.json +6 -6
- package/dist/application-COC0mYEe.js +0 -32
- package/dist/application-n5bk2L_z.d.ts +0 -12
- package/dist/cliFilter-7BSD8Nc_.js +0 -18
- package/dist/cliFilter-DKZxCxSe.d.ts +0 -7
- package/dist/config.default-AcwQOAG0.js +0 -166
- package/dist/config.default-D8v08Vox.d.ts +0 -870
- package/dist/context-C-N1IY85.d.ts +0 -95
- package/dist/context-e-QJTKfq.js +0 -191
- package/dist/csp-BW5AJd_f.js +0 -46
- package/dist/csrf-9aSLHiby.js +0 -33
- package/dist/dta-DVAKEpJ3.js +0 -13
- package/dist/escape-Dex_Pk9e.d.ts +0 -2
- package/dist/escape-p8-cW8c_.js +0 -7
- package/dist/escapeShellArg-BnzDicAC.d.ts +0 -4
- package/dist/escapeShellArg-C0v1ZeCl.js +0 -7
- package/dist/escapeShellCmd-CkAdyhtO.js +0 -15
- package/dist/escapeShellCmd-DQZZIHde.d.ts +0 -4
- package/dist/helper-DylzfQ_5.js +0 -25
- package/dist/hsts-CWMKNTEh.js +0 -19
- package/dist/methodnoallow-BAZONArS.js +0 -15
- package/dist/middlewares-CkQjv8t0.js +0 -27
- package/dist/noopen-C3jUBwoH.js +0 -17
- package/dist/nosniff-CcLkhX2I.js +0 -27
- package/dist/referrerPolicy-D4Uafq6c.js +0 -31
- package/dist/response-BFnHAJrV.js +0 -69
- package/dist/safe_curl-UlViaxoF.js +0 -19
- package/dist/safe_curl-mqZZv_YQ.d.ts +0 -20
- package/dist/shtml-CAquTzgV.d.ts +0 -6
- package/dist/shtml-CgF4kOx-.js +0 -53
- package/dist/sjs-Cbmkk5xS.js +0 -36
- package/dist/sjs-QZIJYS71.d.ts +0 -7
- package/dist/sjson-BetFnVR6.js +0 -32
- package/dist/sjson-O-vKJPws.d.ts +0 -4
- package/dist/spath-Bu9sy6Kz.js +0 -16
- package/dist/spath-DseDPHxf.d.ts +0 -7
- package/dist/surl-ClleTea7.js +0 -25
- package/dist/surl-JV70X_RZ.d.ts +0 -6
- package/dist/types-BZR2U30p.d.ts +0 -38
- package/dist/types-DnJpiSJb.js +0 -1
- package/dist/utils-Cajs5P8M.js +0 -127
- package/dist/xframe-q9fEZkVI.js +0 -18
- package/dist/xssProtection-D5QsHX-e.js +0 -17
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { SecurityConfig } from "./config.default-D8v08Vox.js";
|
|
2
|
-
import { HttpClientOptions, HttpClientRequestURL, HttpClientResponse } from "./safe_curl-mqZZv_YQ.js";
|
|
3
|
-
import { Context, Response } from "egg";
|
|
4
|
-
|
|
5
|
-
//#region src/app/extend/response.d.ts
|
|
6
|
-
declare class SecurityResponse extends Response {
|
|
7
|
-
ctx: SecurityContext;
|
|
8
|
-
/**
|
|
9
|
-
* This is an unsafe redirection, and we WON'T check if the
|
|
10
|
-
* destination url is safe or not.
|
|
11
|
-
* Please DO NOT use this method unless in some very special cases,
|
|
12
|
-
* otherwise there may be security vulnerabilities.
|
|
13
|
-
*
|
|
14
|
-
* @function Response#unsafeRedirect
|
|
15
|
-
* @param {String} url URL to forward
|
|
16
|
-
* @example
|
|
17
|
-
* ```js
|
|
18
|
-
* ctx.response.unsafeRedirect('http://www.domain.com');
|
|
19
|
-
* ctx.unsafeRedirect('http://www.domain.com');
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
unsafeRedirect(url: string, alt?: string): void;
|
|
23
|
-
/**
|
|
24
|
-
* A safe redirection, and we'll check if the URL is in
|
|
25
|
-
* a safe domain or not.
|
|
26
|
-
* We've overridden the default Koa's implementation by adding a
|
|
27
|
-
* white list as the filter for that.
|
|
28
|
-
*
|
|
29
|
-
* @function Response#redirect
|
|
30
|
-
* @param {String} url URL to forward
|
|
31
|
-
* @example
|
|
32
|
-
* ```js
|
|
33
|
-
* ctx.response.redirect('/login');
|
|
34
|
-
* ctx.redirect('/login');
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
redirect(url: string, alt?: string): void;
|
|
38
|
-
}
|
|
39
|
-
//#endregion
|
|
40
|
-
//#region src/app/extend/context.d.ts
|
|
41
|
-
declare const CSRF_SECRET: unique symbol;
|
|
42
|
-
declare const LOG_CSRF_NOTICE: unique symbol;
|
|
43
|
-
declare const INPUT_TOKEN: unique symbol;
|
|
44
|
-
declare const CSRF_REFERER_CHECK: unique symbol;
|
|
45
|
-
declare const CSRF_CTOKEN_CHECK: unique symbol;
|
|
46
|
-
declare class SecurityContext extends Context {
|
|
47
|
-
response: SecurityResponse;
|
|
48
|
-
get securityOptions(): Partial<SecurityConfig>;
|
|
49
|
-
/**
|
|
50
|
-
* Check whether the specific `domain` is in / matches the whiteList or not.
|
|
51
|
-
* @param {string} domain The assigned domain.
|
|
52
|
-
* @param {Array<string>} [customWhiteList] The custom white list for domain.
|
|
53
|
-
* @return {boolean} If the domain is in / matches the whiteList, return true;
|
|
54
|
-
* otherwise false.
|
|
55
|
-
*/
|
|
56
|
-
isSafeDomain(domain: string, customWhiteList?: string[]): boolean;
|
|
57
|
-
get nonce(): string;
|
|
58
|
-
/**
|
|
59
|
-
* get csrf token, general use in template
|
|
60
|
-
* @return {String} csrf token
|
|
61
|
-
* @public
|
|
62
|
-
*/
|
|
63
|
-
get csrf(): string;
|
|
64
|
-
/**
|
|
65
|
-
* get csrf secret from session or cookie
|
|
66
|
-
* @return {String} csrf secret
|
|
67
|
-
* @private
|
|
68
|
-
*/
|
|
69
|
-
get [CSRF_SECRET](): string;
|
|
70
|
-
/**
|
|
71
|
-
* ensure csrf secret exists in session or cookie.
|
|
72
|
-
* @param {Boolean} [rotate] reset secret even if the secret exists
|
|
73
|
-
* @public
|
|
74
|
-
*/
|
|
75
|
-
ensureCsrfSecret(rotate?: boolean): void;
|
|
76
|
-
get [INPUT_TOKEN](): string;
|
|
77
|
-
/**
|
|
78
|
-
* rotate csrf secret exists in session or cookie.
|
|
79
|
-
* must rotate the secret when user login
|
|
80
|
-
* @public
|
|
81
|
-
*/
|
|
82
|
-
rotateCsrfSecret(): void;
|
|
83
|
-
/**
|
|
84
|
-
* assert csrf token/referer is present
|
|
85
|
-
* @public
|
|
86
|
-
*/
|
|
87
|
-
assertCsrf(): void;
|
|
88
|
-
[CSRF_CTOKEN_CHECK](): "missing csrf token" | "invalid csrf token" | undefined;
|
|
89
|
-
[CSRF_REFERER_CHECK](): "missing csrf referer or origin" | "invalid csrf referer or origin" | undefined;
|
|
90
|
-
[LOG_CSRF_NOTICE](msg: string): void;
|
|
91
|
-
safeCurl<T = any>(url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
|
|
92
|
-
unsafeRedirect(url: string, alt?: string): void;
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
export { SecurityContext, SecurityResponse };
|
package/dist/context-e-QJTKfq.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore, getFromUrl, isSafeDomain } from "./utils-Cajs5P8M.js";
|
|
2
|
-
import { Context } from "egg";
|
|
3
|
-
import { debuglog } from "node:util";
|
|
4
|
-
import { nanoid } from "nanoid/non-secure";
|
|
5
|
-
import Tokens from "csrf";
|
|
6
|
-
|
|
7
|
-
//#region src/app/extend/context.ts
|
|
8
|
-
const debug = debuglog("egg/security/app/extend/context");
|
|
9
|
-
const tokens = new Tokens();
|
|
10
|
-
const CSRF_SECRET = Symbol("egg-security#CSRF_SECRET");
|
|
11
|
-
const _CSRF_SECRET = Symbol("egg-security#_CSRF_SECRET");
|
|
12
|
-
const NEW_CSRF_SECRET = Symbol("egg-security#NEW_CSRF_SECRET");
|
|
13
|
-
const LOG_CSRF_NOTICE = Symbol("egg-security#LOG_CSRF_NOTICE");
|
|
14
|
-
const INPUT_TOKEN = Symbol("egg-security#INPUT_TOKEN");
|
|
15
|
-
const NONCE_CACHE = Symbol("egg-security#NONCE_CACHE");
|
|
16
|
-
const SECURITY_OPTIONS = Symbol("egg-security#SECURITY_OPTIONS");
|
|
17
|
-
const CSRF_REFERER_CHECK = Symbol("egg-security#CSRF_REFERER_CHECK");
|
|
18
|
-
const CSRF_CTOKEN_CHECK = Symbol("egg-security#CSRF_CTOKEN_CHECK");
|
|
19
|
-
function findToken(obj, keys) {
|
|
20
|
-
if (!obj) return;
|
|
21
|
-
if (!keys || !keys.length) return;
|
|
22
|
-
if (typeof keys === "string") return obj[keys];
|
|
23
|
-
for (const key of keys) if (obj[key]) return obj[key];
|
|
24
|
-
}
|
|
25
|
-
var SecurityContext = class extends Context {
|
|
26
|
-
get securityOptions() {
|
|
27
|
-
if (!this[SECURITY_OPTIONS]) this[SECURITY_OPTIONS] = {};
|
|
28
|
-
return this[SECURITY_OPTIONS];
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Check whether the specific `domain` is in / matches the whiteList or not.
|
|
32
|
-
* @param {string} domain The assigned domain.
|
|
33
|
-
* @param {Array<string>} [customWhiteList] The custom white list for domain.
|
|
34
|
-
* @return {boolean} If the domain is in / matches the whiteList, return true;
|
|
35
|
-
* otherwise false.
|
|
36
|
-
*/
|
|
37
|
-
isSafeDomain(domain, customWhiteList) {
|
|
38
|
-
const domainWhiteList = customWhiteList && customWhiteList.length > 0 ? customWhiteList : this.app.config.security.domainWhiteList;
|
|
39
|
-
return isSafeDomain(domain, domainWhiteList);
|
|
40
|
-
}
|
|
41
|
-
get nonce() {
|
|
42
|
-
if (!this[NONCE_CACHE]) this[NONCE_CACHE] = nanoid(16);
|
|
43
|
-
return this[NONCE_CACHE];
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* get csrf token, general use in template
|
|
47
|
-
* @return {String} csrf token
|
|
48
|
-
* @public
|
|
49
|
-
*/
|
|
50
|
-
get csrf() {
|
|
51
|
-
const secret = this[NEW_CSRF_SECRET] || this[CSRF_SECRET];
|
|
52
|
-
debug("get csrf token, NEW_CSRF_SECRET: %s, _CSRF_SECRET: %s", this[NEW_CSRF_SECRET], this[CSRF_SECRET]);
|
|
53
|
-
return secret ? tokens.create(secret) : "";
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* get csrf secret from session or cookie
|
|
57
|
-
* @return {String} csrf secret
|
|
58
|
-
* @private
|
|
59
|
-
*/
|
|
60
|
-
get [CSRF_SECRET]() {
|
|
61
|
-
if (this[_CSRF_SECRET]) return this[_CSRF_SECRET];
|
|
62
|
-
let { useSession, sessionName, cookieName: cookieNames, cookieOptions } = this.app.config.security.csrf;
|
|
63
|
-
if (useSession) this[_CSRF_SECRET] = this.session[sessionName] || "";
|
|
64
|
-
else {
|
|
65
|
-
if (!Array.isArray(cookieNames)) cookieNames = [cookieNames];
|
|
66
|
-
for (const cookieName of cookieNames) {
|
|
67
|
-
this[_CSRF_SECRET] = this.cookies.get(cookieName, { signed: cookieOptions.signed }) || "";
|
|
68
|
-
if (this[_CSRF_SECRET]) break;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return this[_CSRF_SECRET];
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* ensure csrf secret exists in session or cookie.
|
|
75
|
-
* @param {Boolean} [rotate] reset secret even if the secret exists
|
|
76
|
-
* @public
|
|
77
|
-
*/
|
|
78
|
-
ensureCsrfSecret(rotate) {
|
|
79
|
-
if (this[CSRF_SECRET] && !rotate) return;
|
|
80
|
-
debug("ensure csrf secret, exists: %s, rotate; %s", this[CSRF_SECRET], rotate);
|
|
81
|
-
const secret = tokens.secretSync();
|
|
82
|
-
this[NEW_CSRF_SECRET] = secret;
|
|
83
|
-
let { useSession, sessionName, cookieDomain, cookieName: cookieNames, cookieOptions } = this.app.config.security.csrf;
|
|
84
|
-
if (useSession) this.session[sessionName] = secret;
|
|
85
|
-
else {
|
|
86
|
-
if (typeof cookieDomain === "function") cookieDomain = cookieDomain(this);
|
|
87
|
-
const cookieOpts = {
|
|
88
|
-
domain: cookieDomain,
|
|
89
|
-
...cookieOptions
|
|
90
|
-
};
|
|
91
|
-
if (!Array.isArray(cookieNames)) cookieNames = [cookieNames];
|
|
92
|
-
for (const cookieName of cookieNames) this.cookies.set(cookieName, secret, cookieOpts);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
get [INPUT_TOKEN]() {
|
|
96
|
-
const { headerName, bodyName, queryName } = this.app.config.security.csrf;
|
|
97
|
-
const token = findToken(this.request.query, queryName) || findToken(this.request.body, bodyName) || headerName && this.request.get(headerName);
|
|
98
|
-
debug("get token: %j, secret: %j", token, this[CSRF_SECRET]);
|
|
99
|
-
return token;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* rotate csrf secret exists in session or cookie.
|
|
103
|
-
* must rotate the secret when user login
|
|
104
|
-
* @public
|
|
105
|
-
*/
|
|
106
|
-
rotateCsrfSecret() {
|
|
107
|
-
if (!this[NEW_CSRF_SECRET] && this[CSRF_SECRET]) this.ensureCsrfSecret(true);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* assert csrf token/referer is present
|
|
111
|
-
* @public
|
|
112
|
-
*/
|
|
113
|
-
assertCsrf() {
|
|
114
|
-
if (checkIfIgnore(this.app.config.security.csrf, this)) {
|
|
115
|
-
debug("%s, ignore by csrf options", this.path);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const { type } = this.app.config.security.csrf;
|
|
119
|
-
let message;
|
|
120
|
-
const messages = [];
|
|
121
|
-
switch (type) {
|
|
122
|
-
case "ctoken":
|
|
123
|
-
message = this[CSRF_CTOKEN_CHECK]();
|
|
124
|
-
if (message) this.throw(403, message);
|
|
125
|
-
break;
|
|
126
|
-
case "referer":
|
|
127
|
-
message = this[CSRF_REFERER_CHECK]();
|
|
128
|
-
if (message) this.throw(403, message);
|
|
129
|
-
break;
|
|
130
|
-
case "all":
|
|
131
|
-
message = this[CSRF_CTOKEN_CHECK]();
|
|
132
|
-
if (message) this.throw(403, message);
|
|
133
|
-
message = this[CSRF_REFERER_CHECK]();
|
|
134
|
-
if (message) this.throw(403, message);
|
|
135
|
-
break;
|
|
136
|
-
case "any":
|
|
137
|
-
message = this[CSRF_CTOKEN_CHECK]();
|
|
138
|
-
if (!message) return;
|
|
139
|
-
messages.push(message);
|
|
140
|
-
message = this[CSRF_REFERER_CHECK]();
|
|
141
|
-
if (!message) return;
|
|
142
|
-
messages.push(message);
|
|
143
|
-
this.throw(403, `both ctoken and referer check error: ${messages.join(", ")}`);
|
|
144
|
-
break;
|
|
145
|
-
default: this.throw(`invalid type ${type}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
[CSRF_CTOKEN_CHECK]() {
|
|
149
|
-
if (!this[CSRF_SECRET]) {
|
|
150
|
-
debug("missing csrf token");
|
|
151
|
-
this[LOG_CSRF_NOTICE]("missing csrf token");
|
|
152
|
-
return "missing csrf token";
|
|
153
|
-
}
|
|
154
|
-
const token = this[INPUT_TOKEN];
|
|
155
|
-
if (token !== this[CSRF_SECRET] && !tokens.verify(this[CSRF_SECRET], token)) {
|
|
156
|
-
debug("verify secret and token error");
|
|
157
|
-
this[LOG_CSRF_NOTICE]("invalid csrf token");
|
|
158
|
-
const { rotateWhenInvalid } = this.app.config.security.csrf;
|
|
159
|
-
if (rotateWhenInvalid) this.rotateCsrfSecret();
|
|
160
|
-
return "invalid csrf token";
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
[CSRF_REFERER_CHECK]() {
|
|
164
|
-
const { refererWhiteList } = this.app.config.security.csrf;
|
|
165
|
-
const referer = (this.headers.referer ?? this.headers.origin ?? "").toLowerCase();
|
|
166
|
-
if (!referer) {
|
|
167
|
-
debug("missing csrf referer or origin");
|
|
168
|
-
this[LOG_CSRF_NOTICE]("missing csrf referer or origin");
|
|
169
|
-
return "missing csrf referer or origin";
|
|
170
|
-
}
|
|
171
|
-
const host = getFromUrl(referer, "host");
|
|
172
|
-
const domainList = refererWhiteList.concat(this.host);
|
|
173
|
-
if (!host || !isSafeDomain(host, domainList)) {
|
|
174
|
-
debug("verify referer or origin error");
|
|
175
|
-
this[LOG_CSRF_NOTICE]("invalid csrf referer or origin");
|
|
176
|
-
return "invalid csrf referer or origin";
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
[LOG_CSRF_NOTICE](msg) {
|
|
180
|
-
if (this.app.config.env === "local") this.logger.warn(`${msg}. See https://eggjs.org/zh-CN/core/security/#%E5%AE%89%E5%85%A8%E5%A8%81%E8%83%81-csrf-%E7%9A%84%E9%98%B2%E8%8C%83`);
|
|
181
|
-
}
|
|
182
|
-
async safeCurl(url, options) {
|
|
183
|
-
return await this.app.safeCurl(url, options);
|
|
184
|
-
}
|
|
185
|
-
unsafeRedirect(url, alt) {
|
|
186
|
-
this.response.unsafeRedirect(url, alt);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
//#endregion
|
|
191
|
-
export { SecurityContext };
|
package/dist/csp-BW5AJd_f.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore } from "./utils-Cajs5P8M.js";
|
|
2
|
-
import extend from "extend";
|
|
3
|
-
|
|
4
|
-
//#region src/lib/middlewares/csp.ts
|
|
5
|
-
const HEADER = ["x-content-security-policy", "content-security-policy"];
|
|
6
|
-
const REPORT_ONLY_HEADER = ["x-content-security-policy-report-only", "content-security-policy-report-only"];
|
|
7
|
-
const MSIE_REGEXP = / MSIE /i;
|
|
8
|
-
var csp_default = (options) => {
|
|
9
|
-
return async function csp(ctx, next) {
|
|
10
|
-
await next();
|
|
11
|
-
const opts = {
|
|
12
|
-
...options,
|
|
13
|
-
...ctx.securityOptions.csp
|
|
14
|
-
};
|
|
15
|
-
if (checkIfIgnore(opts, ctx)) return;
|
|
16
|
-
let finalHeader;
|
|
17
|
-
const matchedOption = extend(true, {}, opts.policy);
|
|
18
|
-
const bufArray = [];
|
|
19
|
-
const headers = opts.reportOnly ? REPORT_ONLY_HEADER : HEADER;
|
|
20
|
-
if (opts.supportIE && MSIE_REGEXP.test(ctx.get("user-agent"))) finalHeader = headers[0];
|
|
21
|
-
else finalHeader = headers[1];
|
|
22
|
-
for (const key in matchedOption) {
|
|
23
|
-
const value = matchedOption[key];
|
|
24
|
-
if (key === "sandbox" && value === true) bufArray.push(key);
|
|
25
|
-
else {
|
|
26
|
-
let values = Array.isArray(value) ? value : [value];
|
|
27
|
-
if (key === "script-src") {
|
|
28
|
-
if (!values.some(function(val) {
|
|
29
|
-
return val.indexOf("nonce-") !== -1;
|
|
30
|
-
})) values.push("'nonce-" + ctx.nonce + "'");
|
|
31
|
-
}
|
|
32
|
-
values = values.map(function(d) {
|
|
33
|
-
if (d.startsWith(".")) d = "*" + d;
|
|
34
|
-
return d;
|
|
35
|
-
});
|
|
36
|
-
bufArray.push(key + " " + values.join(" "));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const headerString = bufArray.join(";");
|
|
40
|
-
ctx.set(finalHeader, headerString);
|
|
41
|
-
ctx.set("x-csp-nonce", ctx.nonce);
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
//#endregion
|
|
46
|
-
export { csp_default };
|
package/dist/csrf-9aSLHiby.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore } from "./utils-Cajs5P8M.js";
|
|
2
|
-
import { debuglog } from "node:util";
|
|
3
|
-
import typeis from "type-is";
|
|
4
|
-
|
|
5
|
-
//#region src/lib/middlewares/csrf.ts
|
|
6
|
-
const debug = debuglog("egg/security/lib/middlewares/csrf");
|
|
7
|
-
var csrf_default = (options) => {
|
|
8
|
-
return function csrf(ctx, next) {
|
|
9
|
-
if (checkIfIgnore(options, ctx)) return next();
|
|
10
|
-
if ([
|
|
11
|
-
"any",
|
|
12
|
-
"all",
|
|
13
|
-
"ctoken"
|
|
14
|
-
].includes(options.type)) ctx.ensureCsrfSecret();
|
|
15
|
-
const method = ctx.method;
|
|
16
|
-
let isSupported = false;
|
|
17
|
-
for (const eachRule of options.supportedRequests) if (eachRule.path.test(ctx.path)) {
|
|
18
|
-
if (eachRule.methods.includes(method)) {
|
|
19
|
-
isSupported = true;
|
|
20
|
-
break;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
if (!isSupported) return next();
|
|
24
|
-
if (options.ignoreJSON && typeis.is(ctx.get("content-type"), "json")) return next();
|
|
25
|
-
const body = ctx.request.body;
|
|
26
|
-
debug("%s %s, got %j", ctx.method, ctx.url, body);
|
|
27
|
-
ctx.assertCsrf();
|
|
28
|
-
return next();
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
//#endregion
|
|
33
|
-
export { csrf_default };
|
package/dist/dta-DVAKEpJ3.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { isSafePath } from "./utils-Cajs5P8M.js";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/middlewares/dta.ts
|
|
4
|
-
var dta_default = () => {
|
|
5
|
-
return function dta(ctx, next) {
|
|
6
|
-
const path = ctx.path;
|
|
7
|
-
if (!isSafePath(path, ctx)) ctx.throw(400);
|
|
8
|
-
return next();
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
export { dta_default };
|
package/dist/escape-p8-cW8c_.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/lib/helper/escapeShellCmd.ts
|
|
2
|
-
const BASIC_ALPHABETS = new Set("#&;`|*?~<>^()[]{}$;'\",\nÿ".split(""));
|
|
3
|
-
function escapeShellCmd(text) {
|
|
4
|
-
const str = "" + text;
|
|
5
|
-
let res = "";
|
|
6
|
-
let ascii;
|
|
7
|
-
for (let index = 0; index < str.length; index++) {
|
|
8
|
-
ascii = str[index];
|
|
9
|
-
if (!BASIC_ALPHABETS.has(ascii)) res += ascii;
|
|
10
|
-
}
|
|
11
|
-
return res;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
//#endregion
|
|
15
|
-
export { escapeShellCmd };
|
package/dist/helper-DylzfQ_5.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { cliFilter } from "./cliFilter-7BSD8Nc_.js";
|
|
2
|
-
import { escape_default } from "./escape-p8-cW8c_.js";
|
|
3
|
-
import { escapeShellArg } from "./escapeShellArg-C0v1ZeCl.js";
|
|
4
|
-
import { escapeShellCmd } from "./escapeShellCmd-CkAdyhtO.js";
|
|
5
|
-
import { shtml } from "./shtml-CgF4kOx-.js";
|
|
6
|
-
import { escapeJavaScript } from "./sjs-Cbmkk5xS.js";
|
|
7
|
-
import { jsonEscape } from "./sjson-BetFnVR6.js";
|
|
8
|
-
import { pathFilter } from "./spath-Bu9sy6Kz.js";
|
|
9
|
-
import { surl } from "./surl-ClleTea7.js";
|
|
10
|
-
|
|
11
|
-
//#region src/lib/helper/index.ts
|
|
12
|
-
var helper_default = {
|
|
13
|
-
cliFilter,
|
|
14
|
-
escape: escape_default,
|
|
15
|
-
escapeShellArg,
|
|
16
|
-
escapeShellCmd,
|
|
17
|
-
shtml,
|
|
18
|
-
sjs: escapeJavaScript,
|
|
19
|
-
sjson: jsonEscape,
|
|
20
|
-
spath: pathFilter,
|
|
21
|
-
surl
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
export { helper_default };
|
package/dist/hsts-CWMKNTEh.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore } from "./utils-Cajs5P8M.js";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/middlewares/hsts.ts
|
|
4
|
-
var hsts_default = (options) => {
|
|
5
|
-
return async function hsts(ctx, next) {
|
|
6
|
-
await next();
|
|
7
|
-
const opts = {
|
|
8
|
-
...options,
|
|
9
|
-
...ctx.securityOptions.hsts
|
|
10
|
-
};
|
|
11
|
-
if (checkIfIgnore(opts, ctx)) return;
|
|
12
|
-
let val = `max-age=${opts.maxAge}`;
|
|
13
|
-
if (opts.includeSubdomains) val = `${val}; includeSubdomains`;
|
|
14
|
-
ctx.set("strict-transport-security", val);
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
export { hsts_default };
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { METHODS } from "node:http";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/middlewares/methodnoallow.ts
|
|
4
|
-
const METHODS_NOT_ALLOWED = ["TRACE", "TRACK"];
|
|
5
|
-
const safeHttpMethodsMap = {};
|
|
6
|
-
for (const method of METHODS) if (!METHODS_NOT_ALLOWED.includes(method)) safeHttpMethodsMap[method.toUpperCase()] = true;
|
|
7
|
-
var methodnoallow_default = () => {
|
|
8
|
-
return function notAllow(ctx, next) {
|
|
9
|
-
if (!safeHttpMethodsMap[ctx.method]) ctx.throw(405);
|
|
10
|
-
return next();
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
//#endregion
|
|
15
|
-
export { methodnoallow_default };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { csp_default } from "./csp-BW5AJd_f.js";
|
|
2
|
-
import { csrf_default } from "./csrf-9aSLHiby.js";
|
|
3
|
-
import { dta_default } from "./dta-DVAKEpJ3.js";
|
|
4
|
-
import { hsts_default } from "./hsts-CWMKNTEh.js";
|
|
5
|
-
import { methodnoallow_default } from "./methodnoallow-BAZONArS.js";
|
|
6
|
-
import { noopen_default } from "./noopen-C3jUBwoH.js";
|
|
7
|
-
import { nosniff_default } from "./nosniff-CcLkhX2I.js";
|
|
8
|
-
import { referrerPolicy_default } from "./referrerPolicy-D4Uafq6c.js";
|
|
9
|
-
import { xframe_default } from "./xframe-q9fEZkVI.js";
|
|
10
|
-
import { xssProtection_default } from "./xssProtection-D5QsHX-e.js";
|
|
11
|
-
|
|
12
|
-
//#region src/lib/middlewares/index.ts
|
|
13
|
-
var middlewares_default = {
|
|
14
|
-
csp: csp_default,
|
|
15
|
-
csrf: csrf_default,
|
|
16
|
-
dta: dta_default,
|
|
17
|
-
hsts: hsts_default,
|
|
18
|
-
methodnoallow: methodnoallow_default,
|
|
19
|
-
noopen: noopen_default,
|
|
20
|
-
nosniff: nosniff_default,
|
|
21
|
-
referrerPolicy: referrerPolicy_default,
|
|
22
|
-
xframe: xframe_default,
|
|
23
|
-
xssProtection: xssProtection_default
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
//#endregion
|
|
27
|
-
export { middlewares_default };
|
package/dist/noopen-C3jUBwoH.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore } from "./utils-Cajs5P8M.js";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/middlewares/noopen.ts
|
|
4
|
-
var noopen_default = (options) => {
|
|
5
|
-
return async function noopen(ctx, next) {
|
|
6
|
-
await next();
|
|
7
|
-
const opts = {
|
|
8
|
-
...options,
|
|
9
|
-
...ctx.securityOptions.noopen
|
|
10
|
-
};
|
|
11
|
-
if (checkIfIgnore(opts, ctx)) return;
|
|
12
|
-
ctx.set("x-download-options", "noopen");
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
export { noopen_default };
|
package/dist/nosniff-CcLkhX2I.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore } from "./utils-Cajs5P8M.js";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/middlewares/nosniff.ts
|
|
4
|
-
const RedirectStatus = {
|
|
5
|
-
300: true,
|
|
6
|
-
301: true,
|
|
7
|
-
302: true,
|
|
8
|
-
303: true,
|
|
9
|
-
305: true,
|
|
10
|
-
307: true,
|
|
11
|
-
308: true
|
|
12
|
-
};
|
|
13
|
-
var nosniff_default = (options) => {
|
|
14
|
-
return async function nosniff(ctx, next) {
|
|
15
|
-
await next();
|
|
16
|
-
if (RedirectStatus[ctx.status]) return;
|
|
17
|
-
const opts = {
|
|
18
|
-
...options,
|
|
19
|
-
...ctx.securityOptions.nosniff
|
|
20
|
-
};
|
|
21
|
-
if (checkIfIgnore(opts, ctx)) return;
|
|
22
|
-
ctx.set("x-content-type-options", "nosniff");
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
//#endregion
|
|
27
|
-
export { nosniff_default };
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { checkIfIgnore } from "./utils-Cajs5P8M.js";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/middlewares/referrerPolicy.ts
|
|
4
|
-
const ALLOWED_POLICIES_ENUM = [
|
|
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
|
-
""
|
|
14
|
-
];
|
|
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
|
-
};
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
//#endregion
|
|
31
|
-
export { referrerPolicy_default };
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Response } from "egg";
|
|
2
|
-
|
|
3
|
-
//#region src/app/extend/response.ts
|
|
4
|
-
const unsafeRedirect = Response.prototype.redirect;
|
|
5
|
-
var SecurityResponse = class extends Response {
|
|
6
|
-
/**
|
|
7
|
-
* This is an unsafe redirection, and we WON'T check if the
|
|
8
|
-
* destination url is safe or not.
|
|
9
|
-
* Please DO NOT use this method unless in some very special cases,
|
|
10
|
-
* otherwise there may be security vulnerabilities.
|
|
11
|
-
*
|
|
12
|
-
* @function Response#unsafeRedirect
|
|
13
|
-
* @param {String} url URL to forward
|
|
14
|
-
* @example
|
|
15
|
-
* ```js
|
|
16
|
-
* ctx.response.unsafeRedirect('http://www.domain.com');
|
|
17
|
-
* ctx.unsafeRedirect('http://www.domain.com');
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
unsafeRedirect(url, alt) {
|
|
21
|
-
unsafeRedirect.call(this, url, alt);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* A safe redirection, and we'll check if the URL is in
|
|
25
|
-
* a safe domain or not.
|
|
26
|
-
* We've overridden the default Koa's implementation by adding a
|
|
27
|
-
* white list as the filter for that.
|
|
28
|
-
*
|
|
29
|
-
* @function Response#redirect
|
|
30
|
-
* @param {String} url URL to forward
|
|
31
|
-
* @example
|
|
32
|
-
* ```js
|
|
33
|
-
* ctx.response.redirect('/login');
|
|
34
|
-
* ctx.redirect('/login');
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
redirect(url, alt) {
|
|
38
|
-
url = (url || "/").trim();
|
|
39
|
-
if (url[0] === "/" && url[1] === "/") url = "/";
|
|
40
|
-
if (url[0] === "/" && url[1] !== "\\") {
|
|
41
|
-
this.unsafeRedirect(url, alt);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
let urlObject;
|
|
45
|
-
try {
|
|
46
|
-
urlObject = new URL(url);
|
|
47
|
-
} catch {
|
|
48
|
-
url = "/";
|
|
49
|
-
this.unsafeRedirect(url);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const domainWhiteList = this.app.config.security.domainWhiteList;
|
|
53
|
-
if (urlObject.protocol !== "http:" && urlObject.protocol !== "https:") url = "/";
|
|
54
|
-
else if (!urlObject.hostname) url = "/";
|
|
55
|
-
else if (domainWhiteList && domainWhiteList.length !== 0) {
|
|
56
|
-
if (!this.ctx.isSafeDomain(urlObject.hostname)) {
|
|
57
|
-
const message = `a security problem has been detected for url "${url}", redirection is prohibited.`;
|
|
58
|
-
if (process.env.NODE_ENV === "production") {
|
|
59
|
-
this.app.coreLogger.warn("[@eggjs/security/response/redirect] %s", message);
|
|
60
|
-
url = "/";
|
|
61
|
-
} else return this.ctx.throw(500, message);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
this.unsafeRedirect(url);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
//#endregion
|
|
69
|
-
export { SecurityResponse };
|