@eggjs/security 5.0.0-beta.18 → 5.0.0-beta.20

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.
Files changed (106) hide show
  1. package/dist/agent.js +1 -1
  2. package/dist/app/extend/agent.d.ts +2 -1
  3. package/dist/app/extend/agent.js +1 -1
  4. package/dist/app/extend/application.d.ts +3 -11
  5. package/dist/app/extend/application.js +2 -30
  6. package/dist/app/extend/context.d.ts +3 -60
  7. package/dist/app/extend/context.js +2 -189
  8. package/dist/app/extend/helper.d.ts +8 -8
  9. package/dist/app/extend/helper.js +11 -1
  10. package/dist/app/extend/response.d.ts +3 -38
  11. package/dist/app/extend/response.js +3 -68
  12. package/dist/app/middleware/securities.js +12 -1
  13. package/dist/app.js +2 -2
  14. package/dist/application-COC0mYEe.js +32 -0
  15. package/dist/application-n5bk2L_z.d.ts +12 -0
  16. package/dist/cliFilter-7BSD8Nc_.js +18 -0
  17. package/dist/cliFilter-DKZxCxSe.d.ts +7 -0
  18. package/dist/config/config.default.d.ts +1 -869
  19. package/dist/config/config.default.js +1 -164
  20. package/dist/config.default-AcwQOAG0.js +166 -0
  21. package/dist/config.default-D8v08Vox.d.ts +870 -0
  22. package/dist/context-C-N1IY85.d.ts +95 -0
  23. package/dist/context-e-QJTKfq.js +191 -0
  24. package/dist/csp-BW5AJd_f.js +46 -0
  25. package/dist/csrf-9aSLHiby.js +33 -0
  26. package/dist/dta-DVAKEpJ3.js +13 -0
  27. package/dist/escape-Dex_Pk9e.d.ts +2 -0
  28. package/dist/escape-p8-cW8c_.js +7 -0
  29. package/dist/escapeShellArg-BnzDicAC.d.ts +4 -0
  30. package/dist/escapeShellArg-C0v1ZeCl.js +7 -0
  31. package/dist/escapeShellCmd-CkAdyhtO.js +15 -0
  32. package/dist/escapeShellCmd-DQZZIHde.d.ts +4 -0
  33. package/dist/helper-DylzfQ_5.js +25 -0
  34. package/dist/hsts-CWMKNTEh.js +19 -0
  35. package/dist/index.d.ts +5 -1
  36. package/dist/index.js +6 -3
  37. package/dist/lib/extend/safe_curl.d.ts +2 -19
  38. package/dist/lib/extend/safe_curl.js +1 -17
  39. package/dist/lib/helper/cliFilter.d.ts +1 -6
  40. package/dist/lib/helper/cliFilter.js +1 -16
  41. package/dist/lib/helper/escape.d.ts +1 -1
  42. package/dist/lib/helper/escape.js +1 -5
  43. package/dist/lib/helper/escapeShellArg.d.ts +1 -3
  44. package/dist/lib/helper/escapeShellArg.js +1 -5
  45. package/dist/lib/helper/escapeShellCmd.d.ts +1 -3
  46. package/dist/lib/helper/escapeShellCmd.js +1 -13
  47. package/dist/lib/helper/index.d.ts +9 -9
  48. package/dist/lib/helper/index.js +11 -23
  49. package/dist/lib/helper/shtml.d.ts +1 -5
  50. package/dist/lib/helper/shtml.js +2 -51
  51. package/dist/lib/helper/sjs.d.ts +1 -6
  52. package/dist/lib/helper/sjs.js +1 -34
  53. package/dist/lib/helper/sjson.d.ts +1 -3
  54. package/dist/lib/helper/sjson.js +2 -30
  55. package/dist/lib/helper/spath.d.ts +1 -6
  56. package/dist/lib/helper/spath.js +1 -14
  57. package/dist/lib/helper/surl.d.ts +1 -5
  58. package/dist/lib/helper/surl.js +1 -23
  59. package/dist/lib/middlewares/csp.d.ts +1 -1
  60. package/dist/lib/middlewares/csp.js +2 -44
  61. package/dist/lib/middlewares/csrf.d.ts +1 -1
  62. package/dist/lib/middlewares/csrf.js +2 -31
  63. package/dist/lib/middlewares/dta.js +2 -11
  64. package/dist/lib/middlewares/hsts.d.ts +1 -1
  65. package/dist/lib/middlewares/hsts.js +2 -17
  66. package/dist/lib/middlewares/index.d.ts +1 -1
  67. package/dist/lib/middlewares/index.js +12 -25
  68. package/dist/lib/middlewares/methodnoallow.js +1 -13
  69. package/dist/lib/middlewares/noopen.d.ts +1 -1
  70. package/dist/lib/middlewares/noopen.js +2 -15
  71. package/dist/lib/middlewares/nosniff.d.ts +1 -1
  72. package/dist/lib/middlewares/nosniff.js +2 -25
  73. package/dist/lib/middlewares/referrerPolicy.d.ts +1 -1
  74. package/dist/lib/middlewares/referrerPolicy.js +2 -29
  75. package/dist/lib/middlewares/xframe.d.ts +1 -1
  76. package/dist/lib/middlewares/xframe.js +2 -16
  77. package/dist/lib/middlewares/xssProtection.d.ts +1 -1
  78. package/dist/lib/middlewares/xssProtection.js +2 -15
  79. package/dist/lib/utils.d.ts +1 -1
  80. package/dist/lib/utils.js +1 -125
  81. package/dist/methodnoallow-BAZONArS.js +15 -0
  82. package/dist/middlewares-CkQjv8t0.js +27 -0
  83. package/dist/noopen-C3jUBwoH.js +17 -0
  84. package/dist/nosniff-CcLkhX2I.js +27 -0
  85. package/dist/referrerPolicy-D4Uafq6c.js +31 -0
  86. package/dist/response-BFnHAJrV.js +69 -0
  87. package/dist/safe_curl-UlViaxoF.js +19 -0
  88. package/dist/safe_curl-mqZZv_YQ.d.ts +20 -0
  89. package/dist/shtml-CAquTzgV.d.ts +6 -0
  90. package/dist/shtml-CgF4kOx-.js +53 -0
  91. package/dist/sjs-Cbmkk5xS.js +36 -0
  92. package/dist/sjs-QZIJYS71.d.ts +7 -0
  93. package/dist/sjson-BetFnVR6.js +32 -0
  94. package/dist/sjson-O-vKJPws.d.ts +4 -0
  95. package/dist/spath-Bu9sy6Kz.js +16 -0
  96. package/dist/spath-DseDPHxf.d.ts +7 -0
  97. package/dist/surl-ClleTea7.js +25 -0
  98. package/dist/surl-JV70X_RZ.d.ts +6 -0
  99. package/dist/types-BZR2U30p.d.ts +38 -0
  100. package/dist/types-DnJpiSJb.js +1 -0
  101. package/dist/types.d.ts +3 -38
  102. package/dist/types.js +2 -0
  103. package/dist/utils-Cajs5P8M.js +127 -0
  104. package/dist/xframe-q9fEZkVI.js +18 -0
  105. package/dist/xssProtection-D5QsHX-e.js +17 -0
  106. package/package.json +8 -8
package/dist/agent.js CHANGED
@@ -1,4 +1,4 @@
1
- import { preprocessConfig } from "./lib/utils.js";
1
+ import { preprocessConfig } from "./utils-Cajs5P8M.js";
2
2
 
3
3
  //#region src/agent.ts
4
4
  var AgentBoot = class {
@@ -1,4 +1,5 @@
1
- import { HttpClientOptions, HttpClientRequestURL, HttpClientResponse } from "../../lib/extend/safe_curl.js";
1
+ import "../../config.default-D8v08Vox.js";
2
+ import { HttpClientOptions, HttpClientRequestURL, HttpClientResponse } from "../../safe_curl-mqZZv_YQ.js";
2
3
  import { Agent } from "egg";
3
4
 
4
5
  //#region src/app/extend/agent.d.ts
@@ -1,4 +1,4 @@
1
- import { safeCurlForApplication } from "../../lib/extend/safe_curl.js";
1
+ import { safeCurlForApplication } from "../../safe_curl-UlViaxoF.js";
2
2
  import { Agent } from "egg";
3
3
 
4
4
  //#region src/app/extend/agent.ts
@@ -1,12 +1,4 @@
1
- import { HttpClientOptions, HttpClientRequestURL, HttpClientResponse } from "../../lib/extend/safe_curl.js";
2
- import { Application } from "egg";
3
-
4
- //#region src/app/extend/application.d.ts
5
- declare class SecurityApplication extends Application {
6
- injectCsrf(html: string): string;
7
- injectNonce(html: string): string;
8
- injectHijackingDefense(html: string): string;
9
- safeCurl<T = any>(url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
10
- }
11
- //#endregion
1
+ import "../../config.default-D8v08Vox.js";
2
+ import "../../safe_curl-mqZZv_YQ.js";
3
+ import { SecurityApplication } from "../../application-n5bk2L_z.js";
12
4
  export { SecurityApplication as default };
@@ -1,32 +1,4 @@
1
- import { safeCurlForApplication } from "../../lib/extend/safe_curl.js";
2
- import { Application } from "egg";
1
+ import "../../safe_curl-UlViaxoF.js";
2
+ import { SecurityApplication } from "../../application-COC0mYEe.js";
3
3
 
4
- //#region src/app/extend/application.ts
5
- const INPUT_CSRF = "\r\n<input type=\"hidden\" name=\"_csrf\" value=\"{{ctx.csrf}}\" /></form>";
6
- const INJECTION_DEFENSE = "<!--for injection--><!--</html>--><!--for injection-->";
7
- var SecurityApplication = class extends Application {
8
- injectCsrf(html) {
9
- html = html.replace(/(<form.*?>)([\s\S]*?)<\/form>/gi, (_, $1, $2) => {
10
- const match = $2;
11
- if (match.indexOf("name=\"_csrf\"") !== -1 || match.indexOf("name='_csrf'") !== -1) return $1 + match + "</form>";
12
- return $1 + match + INPUT_CSRF;
13
- });
14
- return html;
15
- }
16
- injectNonce(html) {
17
- html = html.replace(/<script(.*?)>([\s\S]*?)<\/script[^>]*?>/gi, (_, $1, $2) => {
18
- if (!$1.includes("nonce=")) $1 += " nonce=\"{{ctx.nonce}}\"";
19
- return "<script" + $1 + ">" + $2 + "<\/script>";
20
- });
21
- return html;
22
- }
23
- injectHijackingDefense(html) {
24
- return INJECTION_DEFENSE + html + INJECTION_DEFENSE;
25
- }
26
- async safeCurl(url, options) {
27
- return await safeCurlForApplication(this, url, options);
28
- }
29
- };
30
-
31
- //#endregion
32
4
  export { SecurityApplication as default };
@@ -1,61 +1,4 @@
1
- import { SecurityConfig } from "../../config/config.default.js";
2
- import { HttpClientOptions, HttpClientRequestURL, HttpClientResponse } from "../../lib/extend/safe_curl.js";
3
- import SecurityResponse from "./response.js";
4
- import { Context } from "egg";
5
-
6
- //#region src/app/extend/context.d.ts
7
- declare const CSRF_SECRET: unique symbol;
8
- declare const LOG_CSRF_NOTICE: unique symbol;
9
- declare const INPUT_TOKEN: unique symbol;
10
- declare const CSRF_REFERER_CHECK: unique symbol;
11
- declare const CSRF_CTOKEN_CHECK: unique symbol;
12
- declare class SecurityContext extends Context {
13
- response: SecurityResponse;
14
- get securityOptions(): Partial<SecurityConfig>;
15
- /**
16
- * Check whether the specific `domain` is in / matches the whiteList or not.
17
- * @param {string} domain The assigned domain.
18
- * @param {Array<string>} [customWhiteList] The custom white list for domain.
19
- * @return {boolean} If the domain is in / matches the whiteList, return true;
20
- * otherwise false.
21
- */
22
- isSafeDomain(domain: string, customWhiteList?: string[]): boolean;
23
- get nonce(): string;
24
- /**
25
- * get csrf token, general use in template
26
- * @return {String} csrf token
27
- * @public
28
- */
29
- get csrf(): string;
30
- /**
31
- * get csrf secret from session or cookie
32
- * @return {String} csrf secret
33
- * @private
34
- */
35
- get [CSRF_SECRET](): string;
36
- /**
37
- * ensure csrf secret exists in session or cookie.
38
- * @param {Boolean} [rotate] reset secret even if the secret exists
39
- * @public
40
- */
41
- ensureCsrfSecret(rotate?: boolean): void;
42
- get [INPUT_TOKEN](): string;
43
- /**
44
- * rotate csrf secret exists in session or cookie.
45
- * must rotate the secret when user login
46
- * @public
47
- */
48
- rotateCsrfSecret(): void;
49
- /**
50
- * assert csrf token/referer is present
51
- * @public
52
- */
53
- assertCsrf(): void;
54
- [CSRF_CTOKEN_CHECK](): "missing csrf token" | "invalid csrf token" | undefined;
55
- [CSRF_REFERER_CHECK](): "missing csrf referer or origin" | "invalid csrf referer or origin" | undefined;
56
- [LOG_CSRF_NOTICE](msg: string): void;
57
- safeCurl<T = any>(url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
58
- unsafeRedirect(url: string, alt?: string): void;
59
- }
60
- //#endregion
1
+ import "../../config.default-D8v08Vox.js";
2
+ import "../../safe_curl-mqZZv_YQ.js";
3
+ import { SecurityContext } from "../../context-C-N1IY85.js";
61
4
  export { SecurityContext as default };
@@ -1,191 +1,4 @@
1
- import { checkIfIgnore, getFromUrl, isSafeDomain } from "../../lib/utils.js";
2
- import { Context } from "egg";
3
- import { debuglog } from "node:util";
4
- import { nanoid } from "nanoid/non-secure";
5
- import Tokens from "csrf";
1
+ import "../../utils-Cajs5P8M.js";
2
+ import { SecurityContext } from "../../context-e-QJTKfq.js";
6
3
 
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
4
  export { SecurityContext as default };
@@ -1,11 +1,11 @@
1
- import cliFilter from "../../lib/helper/cliFilter.js";
2
- import escapeShellArg from "../../lib/helper/escapeShellArg.js";
3
- import escapeShellCmd from "../../lib/helper/escapeShellCmd.js";
4
- import shtml from "../../lib/helper/shtml.js";
5
- import escapeJavaScript from "../../lib/helper/sjs.js";
6
- import jsonEscape from "../../lib/helper/sjson.js";
7
- import pathFilter from "../../lib/helper/spath.js";
8
- import surl from "../../lib/helper/surl.js";
1
+ import { cliFilter } from "../../cliFilter-DKZxCxSe.js";
2
+ import { escapeShellArg } from "../../escapeShellArg-BnzDicAC.js";
3
+ import { escapeShellCmd } from "../../escapeShellCmd-DQZZIHde.js";
4
+ import { shtml } from "../../shtml-CAquTzgV.js";
5
+ import { escapeJavaScript } from "../../sjs-QZIJYS71.js";
6
+ import { jsonEscape } from "../../sjson-O-vKJPws.js";
7
+ import { pathFilter } from "../../spath-DseDPHxf.js";
8
+ import { surl } from "../../surl-JV70X_RZ.js";
9
9
  import * as escape_html0 from "escape-html";
10
10
 
11
11
  //#region src/app/extend/helper.d.ts
@@ -1,4 +1,14 @@
1
- import helper_default$1 from "../../lib/helper/index.js";
1
+ import "../../utils-Cajs5P8M.js";
2
+ import "../../cliFilter-7BSD8Nc_.js";
3
+ import "../../escape-p8-cW8c_.js";
4
+ import "../../escapeShellArg-C0v1ZeCl.js";
5
+ import "../../escapeShellCmd-CkAdyhtO.js";
6
+ import "../../shtml-CgF4kOx-.js";
7
+ import "../../sjs-Cbmkk5xS.js";
8
+ import "../../sjson-BetFnVR6.js";
9
+ import "../../spath-Bu9sy6Kz.js";
10
+ import "../../surl-ClleTea7.js";
11
+ import { helper_default as helper_default$1 } from "../../helper-DylzfQ_5.js";
2
12
 
3
13
  //#region src/app/extend/helper.ts
4
14
  var helper_default = { ...helper_default$1 };
@@ -1,39 +1,4 @@
1
- import SecurityContext from "./context.js";
2
- import { Response } from "egg";
3
-
4
- //#region src/app/extend/response.d.ts
5
- declare class SecurityResponse extends Response {
6
- ctx: SecurityContext;
7
- /**
8
- * This is an unsafe redirection, and we WON'T check if the
9
- * destination url is safe or not.
10
- * Please DO NOT use this method unless in some very special cases,
11
- * otherwise there may be security vulnerabilities.
12
- *
13
- * @function Response#unsafeRedirect
14
- * @param {String} url URL to forward
15
- * @example
16
- * ```js
17
- * ctx.response.unsafeRedirect('http://www.domain.com');
18
- * ctx.unsafeRedirect('http://www.domain.com');
19
- * ```
20
- */
21
- unsafeRedirect(url: string, alt?: string): void;
22
- /**
23
- * A safe redirection, and we'll check if the URL is in
24
- * a safe domain or not.
25
- * We've overridden the default Koa's implementation by adding a
26
- * white list as the filter for that.
27
- *
28
- * @function Response#redirect
29
- * @param {String} url URL to forward
30
- * @example
31
- * ```js
32
- * ctx.response.redirect('/login');
33
- * ctx.redirect('/login');
34
- * ```
35
- */
36
- redirect(url: string, alt?: string): void;
37
- }
38
- //#endregion
1
+ import "../../config.default-D8v08Vox.js";
2
+ import "../../safe_curl-mqZZv_YQ.js";
3
+ import { SecurityResponse } from "../../context-C-N1IY85.js";
39
4
  export { SecurityResponse as default };
@@ -1,70 +1,5 @@
1
- import "./context.js";
2
- import { Response } from "egg";
1
+ import "../../utils-Cajs5P8M.js";
2
+ import "../../context-e-QJTKfq.js";
3
+ import { SecurityResponse } from "../../response-BFnHAJrV.js";
3
4
 
4
- //#region src/app/extend/response.ts
5
- const unsafeRedirect = Response.prototype.redirect;
6
- var SecurityResponse = class extends Response {
7
- /**
8
- * This is an unsafe redirection, and we WON'T check if the
9
- * destination url is safe or not.
10
- * Please DO NOT use this method unless in some very special cases,
11
- * otherwise there may be security vulnerabilities.
12
- *
13
- * @function Response#unsafeRedirect
14
- * @param {String} url URL to forward
15
- * @example
16
- * ```js
17
- * ctx.response.unsafeRedirect('http://www.domain.com');
18
- * ctx.unsafeRedirect('http://www.domain.com');
19
- * ```
20
- */
21
- unsafeRedirect(url, alt) {
22
- unsafeRedirect.call(this, url, alt);
23
- }
24
- /**
25
- * A safe redirection, and we'll check if the URL is in
26
- * a safe domain or not.
27
- * We've overridden the default Koa's implementation by adding a
28
- * white list as the filter for that.
29
- *
30
- * @function Response#redirect
31
- * @param {String} url URL to forward
32
- * @example
33
- * ```js
34
- * ctx.response.redirect('/login');
35
- * ctx.redirect('/login');
36
- * ```
37
- */
38
- redirect(url, alt) {
39
- url = (url || "/").trim();
40
- if (url[0] === "/" && url[1] === "/") url = "/";
41
- if (url[0] === "/" && url[1] !== "\\") {
42
- this.unsafeRedirect(url, alt);
43
- return;
44
- }
45
- let urlObject;
46
- try {
47
- urlObject = new URL(url);
48
- } catch {
49
- url = "/";
50
- this.unsafeRedirect(url);
51
- return;
52
- }
53
- const domainWhiteList = this.app.config.security.domainWhiteList;
54
- if (urlObject.protocol !== "http:" && urlObject.protocol !== "https:") url = "/";
55
- else if (!urlObject.hostname) url = "/";
56
- else if (domainWhiteList && domainWhiteList.length !== 0) {
57
- if (!this.ctx.isSafeDomain(urlObject.hostname)) {
58
- const message = `a security problem has been detected for url "${url}", redirection is prohibited.`;
59
- if (process.env.NODE_ENV === "production") {
60
- this.app.coreLogger.warn("[@eggjs/security/response/redirect] %s", message);
61
- url = "/";
62
- } else return this.ctx.throw(500, message);
63
- }
64
- }
65
- this.unsafeRedirect(url);
66
- }
67
- };
68
-
69
- //#endregion
70
5
  export { SecurityResponse as default };
@@ -1,4 +1,15 @@
1
- import middlewares_default from "../../lib/middlewares/index.js";
1
+ import "../../utils-Cajs5P8M.js";
2
+ import "../../csp-BW5AJd_f.js";
3
+ import "../../csrf-9aSLHiby.js";
4
+ import "../../dta-DVAKEpJ3.js";
5
+ import "../../hsts-CWMKNTEh.js";
6
+ import "../../methodnoallow-BAZONArS.js";
7
+ import "../../noopen-C3jUBwoH.js";
8
+ import "../../nosniff-CcLkhX2I.js";
9
+ import "../../referrerPolicy-D4Uafq6c.js";
10
+ import "../../xframe-q9fEZkVI.js";
11
+ import "../../xssProtection-D5QsHX-e.js";
12
+ import { middlewares_default } from "../../middlewares-CkQjv8t0.js";
2
13
  import assert from "node:assert";
3
14
  import compose from "koa-compose";
4
15
  import { pathMatching } from "egg-path-matching";
package/dist/app.js CHANGED
@@ -1,5 +1,5 @@
1
- import { preprocessConfig } from "./lib/utils.js";
2
- import { SecurityConfig } from "./config/config.default.js";
1
+ import { preprocessConfig } from "./utils-Cajs5P8M.js";
2
+ import { SecurityConfig } from "./config.default-AcwQOAG0.js";
3
3
 
4
4
  //#region src/app.ts
5
5
  var AppBoot = class {
@@ -0,0 +1,32 @@
1
+ import { safeCurlForApplication } from "./safe_curl-UlViaxoF.js";
2
+ import { Application } from "egg";
3
+
4
+ //#region src/app/extend/application.ts
5
+ const INPUT_CSRF = "\r\n<input type=\"hidden\" name=\"_csrf\" value=\"{{ctx.csrf}}\" /></form>";
6
+ const INJECTION_DEFENSE = "<!--for injection--><!--</html>--><!--for injection-->";
7
+ var SecurityApplication = class extends Application {
8
+ injectCsrf(html) {
9
+ html = html.replace(/(<form.*?>)([\s\S]*?)<\/form>/gi, (_, $1, $2) => {
10
+ const match = $2;
11
+ if (match.indexOf("name=\"_csrf\"") !== -1 || match.indexOf("name='_csrf'") !== -1) return $1 + match + "</form>";
12
+ return $1 + match + INPUT_CSRF;
13
+ });
14
+ return html;
15
+ }
16
+ injectNonce(html) {
17
+ html = html.replace(/<script(.*?)>([\s\S]*?)<\/script[^>]*?>/gi, (_, $1, $2) => {
18
+ if (!$1.includes("nonce=")) $1 += " nonce=\"{{ctx.nonce}}\"";
19
+ return "<script" + $1 + ">" + $2 + "<\/script>";
20
+ });
21
+ return html;
22
+ }
23
+ injectHijackingDefense(html) {
24
+ return INJECTION_DEFENSE + html + INJECTION_DEFENSE;
25
+ }
26
+ async safeCurl(url, options) {
27
+ return await safeCurlForApplication(this, url, options);
28
+ }
29
+ };
30
+
31
+ //#endregion
32
+ export { SecurityApplication };
@@ -0,0 +1,12 @@
1
+ import { HttpClientOptions, HttpClientRequestURL, HttpClientResponse } from "./safe_curl-mqZZv_YQ.js";
2
+ import { Application } from "egg";
3
+
4
+ //#region src/app/extend/application.d.ts
5
+ declare class SecurityApplication extends Application {
6
+ injectCsrf(html: string): string;
7
+ injectNonce(html: string): string;
8
+ injectHijackingDefense(html: string): string;
9
+ safeCurl<T = any>(url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
10
+ }
11
+ //#endregion
12
+ export { SecurityApplication };
@@ -0,0 +1,18 @@
1
+ //#region src/lib/helper/cliFilter.ts
2
+ /**
3
+ * remote command execution
4
+ */
5
+ const BASIC_ALPHABETS = new Set("abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ.-_".split(""));
6
+ function cliFilter(text) {
7
+ const str = "" + text;
8
+ let res = "";
9
+ let ascii;
10
+ for (let index = 0; index < str.length; index++) {
11
+ ascii = str[index];
12
+ if (BASIC_ALPHABETS.has(ascii)) res += ascii;
13
+ }
14
+ return res;
15
+ }
16
+
17
+ //#endregion
18
+ export { cliFilter };
@@ -0,0 +1,7 @@
1
+ //#region src/lib/helper/cliFilter.d.ts
2
+ /**
3
+ * remote command execution
4
+ */
5
+ declare function cliFilter(text: string): string;
6
+ //#endregion
7
+ export { cliFilter };