@eggjs/security 4.0.0

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 (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +569 -0
  3. package/README.zh-CN.md +441 -0
  4. package/dist/commonjs/agent.d.ts +6 -0
  5. package/dist/commonjs/agent.js +14 -0
  6. package/dist/commonjs/app/extend/agent.d.ts +5 -0
  7. package/dist/commonjs/app/extend/agent.js +11 -0
  8. package/dist/commonjs/app/extend/application.d.ts +16 -0
  9. package/dist/commonjs/app/extend/application.js +35 -0
  10. package/dist/commonjs/app/extend/context.d.ts +68 -0
  11. package/dist/commonjs/app/extend/context.js +283 -0
  12. package/dist/commonjs/app/extend/helper.d.ts +12 -0
  13. package/dist/commonjs/app/extend/helper.js +10 -0
  14. package/dist/commonjs/app/extend/response.d.ts +41 -0
  15. package/dist/commonjs/app/extend/response.js +85 -0
  16. package/dist/commonjs/app/middleware/securities.d.ts +4 -0
  17. package/dist/commonjs/app/middleware/securities.js +55 -0
  18. package/dist/commonjs/app.d.ts +6 -0
  19. package/dist/commonjs/app.js +29 -0
  20. package/dist/commonjs/config/config.default.d.ts +871 -0
  21. package/dist/commonjs/config/config.default.js +357 -0
  22. package/dist/commonjs/config/config.local.d.ts +5 -0
  23. package/dist/commonjs/config/config.local.js +10 -0
  24. package/dist/commonjs/index.d.ts +1 -0
  25. package/dist/commonjs/index.js +14 -0
  26. package/dist/commonjs/lib/extend/safe_curl.d.ts +16 -0
  27. package/dist/commonjs/lib/extend/safe_curl.js +28 -0
  28. package/dist/commonjs/lib/helper/cliFilter.d.ts +4 -0
  29. package/dist/commonjs/lib/helper/cliFilter.js +20 -0
  30. package/dist/commonjs/lib/helper/escape.d.ts +2 -0
  31. package/dist/commonjs/lib/helper/escape.js +8 -0
  32. package/dist/commonjs/lib/helper/escapeShellArg.d.ts +1 -0
  33. package/dist/commonjs/lib/helper/escapeShellArg.js +8 -0
  34. package/dist/commonjs/lib/helper/escapeShellCmd.d.ts +1 -0
  35. package/dist/commonjs/lib/helper/escapeShellCmd.js +17 -0
  36. package/dist/commonjs/lib/helper/index.d.ts +21 -0
  37. package/dist/commonjs/lib/helper/index.js +26 -0
  38. package/dist/commonjs/lib/helper/shtml.d.ts +2 -0
  39. package/dist/commonjs/lib/helper/shtml.js +76 -0
  40. package/dist/commonjs/lib/helper/sjs.d.ts +4 -0
  41. package/dist/commonjs/lib/helper/sjs.js +52 -0
  42. package/dist/commonjs/lib/helper/sjson.d.ts +1 -0
  43. package/dist/commonjs/lib/helper/sjson.js +45 -0
  44. package/dist/commonjs/lib/helper/spath.d.ts +5 -0
  45. package/dist/commonjs/lib/helper/spath.js +28 -0
  46. package/dist/commonjs/lib/helper/surl.d.ts +2 -0
  47. package/dist/commonjs/lib/helper/surl.js +33 -0
  48. package/dist/commonjs/lib/middlewares/csp.d.ts +4 -0
  49. package/dist/commonjs/lib/middlewares/csp.js +68 -0
  50. package/dist/commonjs/lib/middlewares/csrf.d.ts +4 -0
  51. package/dist/commonjs/lib/middlewares/csrf.js +42 -0
  52. package/dist/commonjs/lib/middlewares/dta.d.ts +3 -0
  53. package/dist/commonjs/lib/middlewares/dta.js +14 -0
  54. package/dist/commonjs/lib/middlewares/hsts.d.ts +4 -0
  55. package/dist/commonjs/lib/middlewares/hsts.js +23 -0
  56. package/dist/commonjs/lib/middlewares/index.d.ts +13 -0
  57. package/dist/commonjs/lib/middlewares/index.js +28 -0
  58. package/dist/commonjs/lib/middlewares/methodnoallow.d.ts +3 -0
  59. package/dist/commonjs/lib/middlewares/methodnoallow.js +22 -0
  60. package/dist/commonjs/lib/middlewares/noopen.d.ts +4 -0
  61. package/dist/commonjs/lib/middlewares/noopen.js +17 -0
  62. package/dist/commonjs/lib/middlewares/nosniff.d.ts +4 -0
  63. package/dist/commonjs/lib/middlewares/nosniff.js +30 -0
  64. package/dist/commonjs/lib/middlewares/referrerPolicy.d.ts +4 -0
  65. package/dist/commonjs/lib/middlewares/referrerPolicy.js +36 -0
  66. package/dist/commonjs/lib/middlewares/xframe.d.ts +4 -0
  67. package/dist/commonjs/lib/middlewares/xframe.js +19 -0
  68. package/dist/commonjs/lib/middlewares/xssProtection.d.ts +4 -0
  69. package/dist/commonjs/lib/middlewares/xssProtection.js +16 -0
  70. package/dist/commonjs/lib/utils.d.ts +19 -0
  71. package/dist/commonjs/lib/utils.js +206 -0
  72. package/dist/commonjs/package.json +3 -0
  73. package/dist/commonjs/types.d.ts +10 -0
  74. package/dist/commonjs/types.js +5 -0
  75. package/dist/esm/agent.d.ts +6 -0
  76. package/dist/esm/agent.js +11 -0
  77. package/dist/esm/app/extend/agent.d.ts +5 -0
  78. package/dist/esm/app/extend/agent.js +8 -0
  79. package/dist/esm/app/extend/application.d.ts +16 -0
  80. package/dist/esm/app/extend/application.js +32 -0
  81. package/dist/esm/app/extend/context.d.ts +68 -0
  82. package/dist/esm/app/extend/context.js +244 -0
  83. package/dist/esm/app/extend/helper.d.ts +12 -0
  84. package/dist/esm/app/extend/helper.js +5 -0
  85. package/dist/esm/app/extend/response.d.ts +41 -0
  86. package/dist/esm/app/extend/response.js +82 -0
  87. package/dist/esm/app/middleware/securities.d.ts +4 -0
  88. package/dist/esm/app/middleware/securities.js +50 -0
  89. package/dist/esm/app.d.ts +6 -0
  90. package/dist/esm/app.js +26 -0
  91. package/dist/esm/config/config.default.d.ts +871 -0
  92. package/dist/esm/config/config.default.js +351 -0
  93. package/dist/esm/config/config.local.d.ts +5 -0
  94. package/dist/esm/config/config.local.js +8 -0
  95. package/dist/esm/index.d.ts +1 -0
  96. package/dist/esm/index.js +12 -0
  97. package/dist/esm/lib/extend/safe_curl.d.ts +16 -0
  98. package/dist/esm/lib/extend/safe_curl.js +25 -0
  99. package/dist/esm/lib/helper/cliFilter.d.ts +4 -0
  100. package/dist/esm/lib/helper/cliFilter.js +17 -0
  101. package/dist/esm/lib/helper/escape.d.ts +2 -0
  102. package/dist/esm/lib/helper/escape.js +3 -0
  103. package/dist/esm/lib/helper/escapeShellArg.d.ts +1 -0
  104. package/dist/esm/lib/helper/escapeShellArg.js +5 -0
  105. package/dist/esm/lib/helper/escapeShellCmd.d.ts +1 -0
  106. package/dist/esm/lib/helper/escapeShellCmd.js +14 -0
  107. package/dist/esm/lib/helper/index.d.ts +21 -0
  108. package/dist/esm/lib/helper/index.js +21 -0
  109. package/dist/esm/lib/helper/shtml.d.ts +2 -0
  110. package/dist/esm/lib/helper/shtml.js +70 -0
  111. package/dist/esm/lib/helper/sjs.d.ts +4 -0
  112. package/dist/esm/lib/helper/sjs.js +49 -0
  113. package/dist/esm/lib/helper/sjson.d.ts +1 -0
  114. package/dist/esm/lib/helper/sjson.js +39 -0
  115. package/dist/esm/lib/helper/spath.d.ts +5 -0
  116. package/dist/esm/lib/helper/spath.js +25 -0
  117. package/dist/esm/lib/helper/surl.d.ts +2 -0
  118. package/dist/esm/lib/helper/surl.js +30 -0
  119. package/dist/esm/lib/middlewares/csp.d.ts +4 -0
  120. package/dist/esm/lib/middlewares/csp.js +63 -0
  121. package/dist/esm/lib/middlewares/csrf.d.ts +4 -0
  122. package/dist/esm/lib/middlewares/csrf.js +37 -0
  123. package/dist/esm/lib/middlewares/dta.d.ts +3 -0
  124. package/dist/esm/lib/middlewares/dta.js +12 -0
  125. package/dist/esm/lib/middlewares/hsts.d.ts +4 -0
  126. package/dist/esm/lib/middlewares/hsts.js +21 -0
  127. package/dist/esm/lib/middlewares/index.d.ts +13 -0
  128. package/dist/esm/lib/middlewares/index.js +23 -0
  129. package/dist/esm/lib/middlewares/methodnoallow.d.ts +3 -0
  130. package/dist/esm/lib/middlewares/methodnoallow.js +20 -0
  131. package/dist/esm/lib/middlewares/noopen.d.ts +4 -0
  132. package/dist/esm/lib/middlewares/noopen.js +15 -0
  133. package/dist/esm/lib/middlewares/nosniff.d.ts +4 -0
  134. package/dist/esm/lib/middlewares/nosniff.js +28 -0
  135. package/dist/esm/lib/middlewares/referrerPolicy.d.ts +4 -0
  136. package/dist/esm/lib/middlewares/referrerPolicy.js +34 -0
  137. package/dist/esm/lib/middlewares/xframe.d.ts +4 -0
  138. package/dist/esm/lib/middlewares/xframe.js +17 -0
  139. package/dist/esm/lib/middlewares/xssProtection.d.ts +4 -0
  140. package/dist/esm/lib/middlewares/xssProtection.js +14 -0
  141. package/dist/esm/lib/utils.d.ts +19 -0
  142. package/dist/esm/lib/utils.js +194 -0
  143. package/dist/esm/package.json +3 -0
  144. package/dist/esm/types.d.ts +10 -0
  145. package/dist/esm/types.js +3 -0
  146. package/dist/package.json +4 -0
  147. package/package.json +116 -0
  148. package/src/agent.ts +14 -0
  149. package/src/app/extend/agent.ts +14 -0
  150. package/src/app/extend/application.ts +51 -0
  151. package/src/app/extend/context.ts +282 -0
  152. package/src/app/extend/helper.ts +5 -0
  153. package/src/app/extend/response.ts +95 -0
  154. package/src/app/middleware/securities.ts +63 -0
  155. package/src/app.ts +31 -0
  156. package/src/config/config.default.ts +379 -0
  157. package/src/config/config.local.ts +9 -0
  158. package/src/index.ts +12 -0
  159. package/src/lib/extend/safe_curl.ts +35 -0
  160. package/src/lib/helper/cliFilter.ts +20 -0
  161. package/src/lib/helper/escape.ts +3 -0
  162. package/src/lib/helper/escapeShellArg.ts +4 -0
  163. package/src/lib/helper/escapeShellCmd.ts +16 -0
  164. package/src/lib/helper/index.ts +21 -0
  165. package/src/lib/helper/shtml.ts +77 -0
  166. package/src/lib/helper/sjs.ts +57 -0
  167. package/src/lib/helper/sjson.ts +35 -0
  168. package/src/lib/helper/spath.ts +27 -0
  169. package/src/lib/helper/surl.ts +35 -0
  170. package/src/lib/middlewares/csp.ts +70 -0
  171. package/src/lib/middlewares/csrf.ts +44 -0
  172. package/src/lib/middlewares/dta.ts +13 -0
  173. package/src/lib/middlewares/hsts.ts +24 -0
  174. package/src/lib/middlewares/index.ts +23 -0
  175. package/src/lib/middlewares/methodnoallow.ts +23 -0
  176. package/src/lib/middlewares/noopen.ts +18 -0
  177. package/src/lib/middlewares/nosniff.ts +32 -0
  178. package/src/lib/middlewares/referrerPolicy.ts +39 -0
  179. package/src/lib/middlewares/xframe.ts +20 -0
  180. package/src/lib/middlewares/xssProtection.ts +17 -0
  181. package/src/lib/utils.ts +208 -0
  182. package/src/types.ts +16 -0
  183. package/src/typings/index.d.ts +4 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Alibaba Group Holding Limited and other contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,569 @@
1
+ # @eggjs/security
2
+
3
+ [![NPM version][npm-image]][npm-url]
4
+ [![Node.js CI](https://github.com/eggjs/security/actions/workflows/nodejs.yml/badge.svg)](https://github.com/eggjs/security/actions/workflows/nodejs.yml)
5
+ [![Test coverage][codecov-image]][codecov-url]
6
+ [![Known Vulnerabilities][snyk-image]][snyk-url]
7
+ [![npm download][download-image]][download-url]
8
+ [![Node.js Version](https://img.shields.io/node/v/eggjs/security.svg?style=flat)](https://nodejs.org/en/download/)
9
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://makeapullrequest.com)
10
+ ![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/eggjs/security)
11
+
12
+ [npm-image]: https://img.shields.io/npm/v/@eggjs/security.svg?style=flat-square
13
+ [npm-url]: https://npmjs.org/package/@eggjs/security
14
+ [codecov-image]: https://codecov.io/gh/eggjs/security/branch/master/graph/badge.svg
15
+ [codecov-url]: https://codecov.io/gh/eggjs/security
16
+ [snyk-image]: https://snyk.io/test/npm/@eggjs/security/badge.svg?style=flat-square
17
+ [snyk-url]: https://snyk.io/test/npm/@eggjs/security
18
+ [download-image]: https://img.shields.io/npm/dm/@eggjs/security.svg?style=flat-square
19
+ [download-url]: https://npmjs.org/package/@eggjs/security
20
+
21
+ Egg's default security plugin, generally no need to configure.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm i @eggjs/security
27
+ ```
28
+
29
+ ## Usage & configuration
30
+
31
+ - `config.default.js`
32
+
33
+ ```js
34
+ exports.security = {
35
+ xframe: {
36
+ value: 'SAMEORIGIN',
37
+ },
38
+ };
39
+ ```
40
+
41
+ ### Disable security precautions
42
+
43
+ To disable some security precautions, set `enable` property to 'false' directly.
44
+
45
+ For example, disable xframe defense:
46
+
47
+ ```js
48
+ exports.security = {
49
+ xframe: {
50
+ enable: false,
51
+ },
52
+ };
53
+ ```
54
+
55
+ ### match & ignore
56
+
57
+ If you want to set security config open for a certain path, you can configure `match` option.
58
+
59
+ For example, just open csp when path contains `/example`, you can configure with the following configuration:
60
+
61
+ ```js
62
+ exports.security = {
63
+ csp: {
64
+ match: '/example',
65
+ // match: /^\/api/, // support regexp
66
+ // match: ctx => ctx.path.startsWith('/api'), // support function
67
+ // match: [ ctx => ctx.path.startsWith('/api'), /^\/foo$/, '/bar'], // support Array
68
+ policy: {
69
+ //...
70
+ },
71
+ },
72
+ };
73
+ ```
74
+
75
+ If you want to set security config disable for a certain path, you can configure `ignore` option.
76
+
77
+ For example, just disable xframe when path contains `/example` while our pages can be embedded in cooperative businesses , you can configure with the following configuration:
78
+
79
+ ```js
80
+ exports.security = {
81
+ xframe: {
82
+ ignore: '/example',
83
+ // ignore: /^\/api/, // support regexp
84
+ // ignore: ctx => ctx.path.startsWith('/api'), // support function
85
+ // ignore: [ ctx => ctx.path.startsWith('/api'), /^\/foo$/, '/bar'], // support Array
86
+ // ...
87
+ },
88
+ };
89
+ ```
90
+
91
+ __mention:`match` has higher priority than `ignore`__
92
+
93
+ ### Dynamic configuration for security plugins depend on context
94
+
95
+ There are times when we want to be more flexible to configure security plugins.For example:
96
+
97
+ 1. To decide whether to enable or disable the xframe security header from the context of the request.
98
+ 2. To decide csp policies from different request urls.
99
+
100
+ Then we can configure `ctx.securityOptions[name] opts` in the custom middleware or controller, then the current request configuration will override the default configuration (new configuration will be merged and override the default project configuration, but only take effect in the current request)
101
+
102
+ ```js
103
+ async ctx => {
104
+ // if satisfied some condition
105
+ // change configuration
106
+ ctx.securityOptions.xframe = {
107
+ value: 'ALLOW-FROM: https://domain.com',
108
+ };
109
+ // disable configuration
110
+ ctx.securityOptions.xssProtection = {
111
+ enable: false,
112
+ }
113
+ }
114
+ ```
115
+
116
+ Not all security plugins support dynamic configuration, only the following plugins list support
117
+
118
+ - csp
119
+ - hsts
120
+ - noopen
121
+ - nosniff
122
+ - xframe
123
+ - xssProtection
124
+
125
+ And in ` helper `:
126
+
127
+ - shtml
128
+
129
+ helper is the same way to configure.
130
+
131
+ ```js
132
+ ctx.securityOptions.shtml = {
133
+ whiteList: {
134
+ },
135
+ };
136
+ ```
137
+
138
+ #### Mention
139
+
140
+ - Security is a big thing, please pay attention to the risk of changes in the security configuration (especially dynamic changes)
141
+ - `ctx.securityOptions` the current request configuration will overrides the default configuration, but it does not make a deep copy,so pay attention to configure `csp.policy`, it will not be merged.
142
+ - If you configure `ctx.securityOptions`,please write unit tests to ensure the code is correct.
143
+
144
+ ## API
145
+
146
+ ### ctx.isSafeDomain(domain)
147
+
148
+ Whether or not the domain is in the whitelist of the configuration. See `ctx.redirect`.
149
+
150
+ Note: [egg-cors](https://github.com/eggjs/egg-cors) module uses this function internally to determine whether or not send back an `Access-Control-Allow-Origin` response header with the value of safe domain. Otherwise, ignore the request with an error, `No 'Access-Control-Allow-Origin' header is present on the requested resource.`
151
+
152
+ ```js
153
+ exports.security = {
154
+ domainWhiteList: ['http://localhost:4200']
155
+ };
156
+ ```
157
+
158
+ ## Interface restriction
159
+
160
+ ### CSRF
161
+
162
+ __usage__
163
+
164
+ - `ctx.csrf` getter for CSRF token
165
+
166
+ Generally used when send POST form request. When page rendering, put `ctx.csrf` into form hidden field or query string.(`_csrf` is the key).
167
+ When submitting the form, please submit with the `_csrf` token parameter.
168
+
169
+ #### Using CSRF when upload by formData
170
+
171
+ browser:
172
+
173
+ ```html
174
+ <form method="POST" action="/upload?_csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data">
175
+ title: <input name="title" />
176
+ file: <input name="file" type="file" />
177
+ <button type="submit">上传</button>
178
+ </form>
179
+ ```
180
+
181
+ #### Using CSRF when request by AJAX
182
+
183
+ CSRF token will also set to cookie by default, and you can send token through header:
184
+
185
+ In jQuery:
186
+
187
+ ```js
188
+ var csrftoken = Cookies.get('csrftoken');
189
+
190
+ function csrfSafeMethod(method) {
191
+ // these HTTP methods do not require CSRF protection
192
+ return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
193
+ }
194
+ $.ajaxSetup({
195
+ beforeSend: function(xhr, settings) {
196
+ if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
197
+ xhr.setRequestHeader('x-csrf-token', csrftoken);
198
+ }
199
+ },
200
+ });
201
+ ```
202
+
203
+ #### Options
204
+
205
+ there are some options that you can customize:
206
+
207
+ ```js
208
+ exports.security = {
209
+ csrf: {
210
+ type: 'ctoken', // can be ctoken, referer, all or any, default to ctoken
211
+ useSession: false, // if useSession set to true, the secret will keep in session instead of cookie
212
+ ignoreJSON: false, // skip check JSON requests if ignoreJSON set to true
213
+ cookieName: 'csrfToken', // csrf token's cookie name
214
+ sessionName: 'csrfToken', // csrf token's session name
215
+ headerName: 'x-csrf-token', // request csrf token's name in header
216
+ bodyName: '_csrf', // request csrf token's name in body
217
+ queryName: '_csrf', // request csrf token's name in query
218
+ rotateWhenInvalid: false, // rotate csrf secret when csrf token invalid. For multi applications which be deployed on the same domain, as tokens from one application may impact others.
219
+ refererWhiteList: [], // referer white list
220
+ supportedRequests: [ // supported URL path and method, the package will match URL path regex patterns one by one until path matched. We recommend you set {path: /^\//, methods:['POST','PATCH','DELETE','PUT','CONNECT']} as the last rule in the list, which is also the default config.
221
+ {path: /^\//, methods:['POST','PATCH','DELETE','PUT','CONNECT']}
222
+ ],
223
+ cookieOptions: {}, // csrf token's cookie options
224
+ },
225
+ }
226
+ ```
227
+
228
+ `methods` in `supportedRequests` can be empty, which means if you set `supportedRequests: [{path: /.*/, methods:[]}]`, the whole csrf protection will be disabled.
229
+
230
+ #### Rotate CSRF secret
231
+
232
+ Must call `ctx.rotateCsrfSecret()` when user login to ensure each user has independent secret.
233
+
234
+ ### safe redirect
235
+
236
+ - `ctx.redirect(url)` If url is not in the configuration of the white list, the redirect will be prohibited
237
+
238
+ - `ctx.unsafeRedirect(url)` Not Recommended;
239
+
240
+ Security plugin override `ctx.redirect` method,all redirects will be judged by the domain name.
241
+
242
+ If you need to use `ctx.redirect`, you need to do the following configuration in the application configuration file:
243
+
244
+ ```js
245
+ exports.security = {
246
+ domainWhiteList:['.domain.com'], // security whitelist, starts with '.'
247
+ };
248
+ ```
249
+
250
+ If user do not configure `domainWhiteList` or `domainWhiteList` is empty, it will pass all redirects, equal to `ctx.unsafeRedirect(url)`. `domainWhiteList` and `url` are case insensitive.
251
+
252
+ ### jsonp
253
+
254
+ Based on [jsonp-body](https://github.com/node-modules/jsonp-body).
255
+
256
+ Defense:
257
+
258
+ - The longest callback function name limit of 50 characters.
259
+ - Callback function only allows "[","]","a-zA-Z0123456789_", "$" "." to prevent `xss` or `utf-7` attack.
260
+
261
+ Config:
262
+
263
+ - callback function default name `_callback`.
264
+ - limit - function name limit, default by 50.
265
+
266
+ ## helper
267
+
268
+ ### .escape()
269
+
270
+ String xss filter, the most secure filtering mechanism.
271
+
272
+ ```js
273
+ const str = '><script>alert("abc") </script><';
274
+ console.log(ctx.helper.escape(str));
275
+ // => &gt;&lt;script&gt;alert(&quot;abc&quot;) &lt;/script&gt;&lt;
276
+ ```
277
+
278
+ In nunjucks template, escape by default.
279
+
280
+ ### .surl()
281
+
282
+ url filter.
283
+
284
+ Used for url in html tags (like `<a href=""/><img src=""/>`),please do not call under other places.
285
+
286
+ `helper.surl($value)`。
287
+
288
+ **Mention: Particular attention, if you need to resolve URL use `surl`,`surl` need warpped in quotes, Otherwise will lead to XSS vulnerability.**
289
+
290
+ Example: do not use surl
291
+
292
+ ```html
293
+ <a href="$value" />
294
+ ```
295
+
296
+ output:
297
+
298
+ ```html
299
+ <a href="http://ww.domain.com<script>" />
300
+ ```
301
+
302
+ Use surl
303
+
304
+ ```html
305
+ <a href="helper.surl($value)" />
306
+ ```
307
+
308
+ output:
309
+
310
+ ```html
311
+ <a href="http://ww.domain.com&lt;script&gt;" />
312
+ ```
313
+
314
+ #### protocolWhitelist
315
+
316
+ If url's protocol is not in the protocol whitelist, it will return empty string.
317
+
318
+ Protocol whitelist is `http`, `https`, `file`, `data`.
319
+
320
+ So if you want `surl` support custom protocol, please extend the security `protocolWhitelist` config :
321
+
322
+ ```js
323
+ exports.security = {
324
+ protocolWhitelist: ['test']
325
+ };
326
+ ```
327
+
328
+ ### .sjs()
329
+
330
+ Used to output variables in javascript(include onload/event),it will do `JAVASCRIPT ENCODE` for the variable string.It will escape all characters to `\x` which are not in the whitelist to avoid XSS attack.
331
+
332
+ ```js
333
+ const foo = '"hello"';
334
+
335
+ // not use sjs
336
+ console.log(`var foo = "${foo}";`);
337
+ // => var foo = ""hello"";
338
+
339
+ // use sjs
340
+ console.log(`var foo = "${ctx.helper.sjs(foo)}";`);
341
+ // => var foo = "\\x22hello\\x22";
342
+ ```
343
+
344
+ ### .shtml()
345
+
346
+ If you want to output richtexts in views, you need to use `shtml` helper.
347
+ It will do XSS filter, then output html tags to avoid illegal scripts.
348
+
349
+ **shtml is a very complex process, it will effect server performance, so if you do not need to output HTML, please do not use shtml.**
350
+
351
+ Examples:
352
+
353
+ ```js
354
+ // js
355
+ const value = `<a href="http://www.domain.com">google</a><script>evilcode…</script>`;
356
+
357
+ // in your view
358
+ <html>
359
+ <body>
360
+ ${helper.shtml($value)}
361
+ </body>
362
+ </html>
363
+ // => <a href="http://www.domain.com">google</a>&lt;script&gt;evilcode…&lt;/script&gt;
364
+ ```
365
+
366
+ shtml based on [xss](https://github.com/leizongmin/js-xss/), and add filter by domain feature.
367
+
368
+ - [default rule](https://github.com/leizongmin/js-xss/blob/master/lib/default.js)
369
+ - custom rule <http://jsxss.com/zh/options.html>
370
+
371
+ For example, only support `a` tag, and filter all attributes except for `title`:
372
+
373
+ ```javascript
374
+ whiteList: {a: ['title']}
375
+ ```
376
+
377
+ options:
378
+
379
+ > `config.helper.shtml.domainWhiteList` has been deprecated, please use `config.security.domainWhiteList` instead.
380
+
381
+ Mention that `shtml` uses a strict white list mechanism, in addition to filtering out the XSS risk of the string,`tags` and `attrs` which are not in the [default rule](https://github.com/leizongmin/js-xss/blob/master/lib/default.js) will be filtered.
382
+
383
+ For example `html` tag is not in the whitelist.
384
+
385
+ ```js
386
+ const html = '<html></html>';
387
+
388
+ // html
389
+ ${helper.shtml($html)}
390
+
391
+ // output none
392
+ ```
393
+
394
+ Commonly used `data-xx` property is not in the whitelist, so it will be filtered.
395
+ So please check the applicable scenarios for `shtml`, it is usually used for rich-text submitted by user.
396
+
397
+ A usage error will limit functions, and also affect the performance of the server.
398
+ Such scenes are generally forums, comments, etc.
399
+
400
+ Even if the forum does not support the HTML content input, do not use this helper, you can directly use `escape` instead.
401
+
402
+ ### .spath()
403
+
404
+ If you want to use users input for a file path, please use spath for security check. If path is illegal, it will return null.
405
+
406
+ Illegal path:
407
+
408
+ - relative path starts with `..`
409
+ - absolute path starts with `/`
410
+ - above path try to use `url encode` to bypass the check
411
+
412
+ ```js
413
+ const foo = '/usr/local/bin';
414
+ console.log(ctx.helper.spath(foo2));
415
+ // => null
416
+ ```
417
+
418
+ ### .sjson()
419
+
420
+ json encode.
421
+
422
+ If you want to output json in javascript without encoding, it will be a risk for XSS.
423
+ sjson supports json encode,it will iterate all keys in json, then escape all characters in the value to `\x` to avoid XSS attack, and keep the json structure unchanged.
424
+ If you want to output json string in your views, please use `${ctx.helper.sjson(var)}`to escape.
425
+
426
+ __it has a very complex process and will lost performance, so avoid the use as far as possible__
427
+
428
+ example:
429
+
430
+ ```js
431
+ <script>
432
+ window.locals = ${ctx.helper.sjson(locals)};
433
+ </script>
434
+ ```
435
+
436
+ ### .cliFilter()
437
+
438
+ It will cause remote command execution vulnerability, when user submit the implementation of the command by browser.because the server does not filter for the implementation of the function, resulting in the execution of the command can usually lead to the invasion of the server.
439
+
440
+ If you want to get user submit for command's parameter, please use `cliFilter`。
441
+
442
+ before fix:
443
+
444
+ ```js
445
+
446
+ cp.exec("bash /home/admin/ali-knowledge-graph-backend/initrun.sh " + port);
447
+
448
+ ```
449
+
450
+ after fix:
451
+
452
+ ```js
453
+
454
+ cp.exec("bash /home/admin/ali-knowledge-graph-backend/initrun.sh " + ctx.helper.cliFilter(port));
455
+
456
+ ```
457
+
458
+ ### .escapeShellArg()
459
+
460
+ Escape command line arguments. Add single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument.
461
+
462
+ ```js
463
+ const ip = '127.0.0.1 && cat /etc/passwd'
464
+ const cmd = 'ping -c 1 ' + this.helper.escapeShellArg(ip);
465
+
466
+ console.log(cmd);
467
+ //ping -c 1 '127.0.0.1 && cat /etc/passwd'
468
+ ```
469
+
470
+ ### .escapeShellCmd()
471
+
472
+ Command line escape to remove the following characters from the entered command line: ```#&;`|*?~<>^()[]{}$;'", 0x0A and 0xFF```
473
+
474
+ ```js
475
+ const ip = '127.0.0.1 && cat /etc/passwd'
476
+ const cmd = 'ping -c 1 ' + this.helper.escapeShellCmd(ip);
477
+
478
+ console.log(cmd);
479
+ //ping -c 1 127.0.0.1 cat /etc/passwd
480
+ ```
481
+
482
+ ## Security Headers
483
+
484
+ Refer to [lusca](https://github.com/krakenjs/lusca), appreciate their work.
485
+
486
+ ### hsts Strict-Transport-Security
487
+
488
+ Disabled by default. If your website based on https, we recommend you should enable it.
489
+
490
+ - maxAge one year by default `365 * 24 * 3600`
491
+ - includeSubdomains false by default
492
+
493
+ ### csp
494
+
495
+ Default disabled. If you need to enable it, please contact your security engineers and determine the opening strategy
496
+
497
+ - policy policies used by csp
498
+
499
+ ### X-Download-Options:noopen
500
+
501
+ Default enabled, disable IE download dialog automatically opens download file and will cause XSS
502
+
503
+ ### X-Content-Type-Options:nosniff
504
+
505
+ Disable IE8's auto MIME sniffing. E.g.: take `text/plain` as `text/html` by mistake and render it, especially when there's something untrusted in the local service.
506
+
507
+ ### X-Frame-Options
508
+
509
+ Defaulting to "SAMEORIGIN", only allows iframe to embed by the same origin.
510
+
511
+ - value Defaulting to `SAMEORIGIN`
512
+
513
+ ### X-XSS-Protection
514
+
515
+ - disable Defaulting to `false`, the same as `1; mode=block`.
516
+
517
+ ### SSRF Protection
518
+
519
+ In a [Server-Side Request Forgery (SSRF)](https://www.owasp.org/index.php/Server_Side_Request_Forgery) attack, the attacker can abuse functionality on the server to read or update internal resources.
520
+
521
+ `egg-security` provide `ctx.safeCurl`, `app.safeCurl` and `agent.safeCurl` to provide http request(like `ctx.curl`, `app.curl` and `agent.curl`) with SSRF protection.
522
+
523
+ #### Configuration
524
+
525
+ - ipBlackList(Array) - specific which IP addresses are illegal when requested with `safeCurl`.
526
+ - ipExceptionList(Array) - specific which IP addresses are legal within ipBlackList.
527
+ hostnameExceptionList(Array) - specifies which hostnames are legal within ipBlackList.
528
+ - checkAddress(Function) - determine the ip by the function's return value, `false` means illegal ip.
529
+
530
+ ```js
531
+ // config/config.default.js
532
+ exports.security = {
533
+ ssrf: {
534
+ // support both cidr subnet or specific IP
535
+ ipBlackList: [
536
+ '10.0.0.0/8',
537
+ '127.0.0.1',
538
+ '0.0.0.0/32',
539
+ ],
540
+ // support both cidr subnet or specific IP
541
+ ipExceptionList: [
542
+ '10.1.1.1',
543
+ '10.10.0.1/24',
544
+ ],
545
+ // legal hostname
546
+ hostnameExceptionList: [
547
+ 'example.com',
548
+ ],
549
+ // checkAddress has higher priority than ipBlackList
550
+ checkAddress(ip) {
551
+ return ip !== '127.0.0.1';
552
+ }
553
+ },
554
+ };
555
+ ```
556
+
557
+ ## Other
558
+
559
+ - Forbid `trace` `track` http methods.
560
+
561
+ ## License
562
+
563
+ [MIT](LICENSE)
564
+
565
+ ## Contributors
566
+
567
+ [![Contributors](https://contrib.rocks/image?repo=eggjs/security)](https://github.com/eggjs/security/graphs/contributors)
568
+
569
+ Made with [contributors-img](https://contrib.rocks).