@eggjs/security 4.0.0 → 5.0.0-beta.15

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 (252) hide show
  1. package/README.md +47 -67
  2. package/README.zh-CN.md +56 -68
  3. package/dist/agent.d.ts +10 -0
  4. package/dist/agent.js +15 -0
  5. package/dist/app/extend/agent.d.ts +14 -0
  6. package/dist/app/extend/agent.js +12 -0
  7. package/dist/app/extend/application.d.ts +20 -0
  8. package/dist/app/extend/application.js +32 -0
  9. package/dist/app/extend/context.d.ts +74 -0
  10. package/dist/app/extend/context.js +191 -0
  11. package/dist/app/extend/helper.d.ts +24 -0
  12. package/dist/app/extend/helper.js +7 -0
  13. package/dist/app/extend/response.d.ts +45 -0
  14. package/dist/app/extend/response.js +70 -0
  15. package/dist/app/middleware/securities.d.ts +8 -0
  16. package/dist/app/middleware/securities.js +39 -0
  17. package/dist/app.d.ts +10 -0
  18. package/dist/app.js +24 -0
  19. package/dist/config/config.default.d.ts +874 -0
  20. package/dist/config/config.default.js +170 -0
  21. package/dist/config/config.local.d.ts +6 -0
  22. package/dist/config/config.local.js +5 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +3 -0
  25. package/dist/lib/extend/safe_curl.d.ts +20 -0
  26. package/dist/lib/extend/safe_curl.js +19 -0
  27. package/dist/lib/helper/cliFilter.d.ts +7 -0
  28. package/dist/lib/helper/cliFilter.js +18 -0
  29. package/dist/lib/helper/escape.d.ts +2 -0
  30. package/dist/lib/helper/escape.js +7 -0
  31. package/dist/lib/helper/escapeShellArg.d.ts +4 -0
  32. package/dist/lib/helper/escapeShellArg.js +7 -0
  33. package/dist/lib/helper/escapeShellCmd.d.ts +4 -0
  34. package/dist/lib/helper/escapeShellCmd.js +15 -0
  35. package/dist/lib/helper/index.d.ts +24 -0
  36. package/dist/lib/helper/index.js +25 -0
  37. package/dist/lib/helper/shtml.d.ts +6 -0
  38. package/dist/lib/helper/shtml.js +53 -0
  39. package/dist/lib/helper/sjs.d.ts +7 -0
  40. package/dist/lib/helper/sjs.js +36 -0
  41. package/dist/lib/helper/sjson.d.ts +4 -0
  42. package/dist/lib/helper/sjson.js +32 -0
  43. package/dist/lib/helper/spath.d.ts +7 -0
  44. package/dist/lib/helper/spath.js +16 -0
  45. package/dist/lib/helper/surl.d.ts +6 -0
  46. package/dist/lib/helper/surl.js +25 -0
  47. package/dist/lib/middlewares/csp.d.ts +7 -0
  48. package/dist/lib/middlewares/csp.js +46 -0
  49. package/dist/lib/middlewares/csrf.d.ts +7 -0
  50. package/dist/lib/middlewares/csrf.js +33 -0
  51. package/dist/lib/middlewares/dta.d.ts +6 -0
  52. package/dist/lib/middlewares/dta.js +13 -0
  53. package/dist/lib/middlewares/hsts.d.ts +7 -0
  54. package/dist/lib/middlewares/hsts.js +19 -0
  55. package/dist/lib/middlewares/index.d.ts +18 -0
  56. package/dist/lib/middlewares/index.js +27 -0
  57. package/dist/lib/middlewares/methodnoallow.d.ts +6 -0
  58. package/dist/lib/middlewares/methodnoallow.js +15 -0
  59. package/dist/lib/middlewares/noopen.d.ts +7 -0
  60. package/dist/lib/middlewares/noopen.js +17 -0
  61. package/dist/lib/middlewares/nosniff.d.ts +7 -0
  62. package/dist/lib/middlewares/nosniff.js +27 -0
  63. package/dist/lib/middlewares/referrerPolicy.d.ts +7 -0
  64. package/dist/lib/middlewares/referrerPolicy.js +31 -0
  65. package/dist/lib/middlewares/xframe.d.ts +7 -0
  66. package/dist/lib/middlewares/xframe.js +18 -0
  67. package/dist/lib/middlewares/xssProtection.d.ts +7 -0
  68. package/dist/lib/middlewares/xssProtection.js +17 -0
  69. package/dist/lib/utils.d.ts +24 -0
  70. package/dist/lib/utils.js +127 -0
  71. package/dist/types.d.ts +12 -0
  72. package/dist/types.js +5 -0
  73. package/package.json +74 -70
  74. package/dist/commonjs/agent.d.ts +0 -6
  75. package/dist/commonjs/agent.js +0 -14
  76. package/dist/commonjs/app/extend/agent.d.ts +0 -5
  77. package/dist/commonjs/app/extend/agent.js +0 -11
  78. package/dist/commonjs/app/extend/application.d.ts +0 -16
  79. package/dist/commonjs/app/extend/application.js +0 -35
  80. package/dist/commonjs/app/extend/context.d.ts +0 -68
  81. package/dist/commonjs/app/extend/context.js +0 -283
  82. package/dist/commonjs/app/extend/helper.d.ts +0 -12
  83. package/dist/commonjs/app/extend/helper.js +0 -10
  84. package/dist/commonjs/app/extend/response.d.ts +0 -41
  85. package/dist/commonjs/app/extend/response.js +0 -85
  86. package/dist/commonjs/app/middleware/securities.d.ts +0 -4
  87. package/dist/commonjs/app/middleware/securities.js +0 -55
  88. package/dist/commonjs/app.d.ts +0 -6
  89. package/dist/commonjs/app.js +0 -29
  90. package/dist/commonjs/config/config.default.d.ts +0 -871
  91. package/dist/commonjs/config/config.default.js +0 -357
  92. package/dist/commonjs/config/config.local.d.ts +0 -5
  93. package/dist/commonjs/config/config.local.js +0 -10
  94. package/dist/commonjs/index.d.ts +0 -1
  95. package/dist/commonjs/index.js +0 -14
  96. package/dist/commonjs/lib/extend/safe_curl.d.ts +0 -16
  97. package/dist/commonjs/lib/extend/safe_curl.js +0 -28
  98. package/dist/commonjs/lib/helper/cliFilter.d.ts +0 -4
  99. package/dist/commonjs/lib/helper/cliFilter.js +0 -20
  100. package/dist/commonjs/lib/helper/escape.d.ts +0 -2
  101. package/dist/commonjs/lib/helper/escape.js +0 -8
  102. package/dist/commonjs/lib/helper/escapeShellArg.d.ts +0 -1
  103. package/dist/commonjs/lib/helper/escapeShellArg.js +0 -8
  104. package/dist/commonjs/lib/helper/escapeShellCmd.d.ts +0 -1
  105. package/dist/commonjs/lib/helper/escapeShellCmd.js +0 -17
  106. package/dist/commonjs/lib/helper/index.d.ts +0 -21
  107. package/dist/commonjs/lib/helper/index.js +0 -26
  108. package/dist/commonjs/lib/helper/shtml.d.ts +0 -2
  109. package/dist/commonjs/lib/helper/shtml.js +0 -76
  110. package/dist/commonjs/lib/helper/sjs.d.ts +0 -4
  111. package/dist/commonjs/lib/helper/sjs.js +0 -52
  112. package/dist/commonjs/lib/helper/sjson.d.ts +0 -1
  113. package/dist/commonjs/lib/helper/sjson.js +0 -45
  114. package/dist/commonjs/lib/helper/spath.d.ts +0 -5
  115. package/dist/commonjs/lib/helper/spath.js +0 -28
  116. package/dist/commonjs/lib/helper/surl.d.ts +0 -2
  117. package/dist/commonjs/lib/helper/surl.js +0 -33
  118. package/dist/commonjs/lib/middlewares/csp.d.ts +0 -4
  119. package/dist/commonjs/lib/middlewares/csp.js +0 -68
  120. package/dist/commonjs/lib/middlewares/csrf.d.ts +0 -4
  121. package/dist/commonjs/lib/middlewares/csrf.js +0 -42
  122. package/dist/commonjs/lib/middlewares/dta.d.ts +0 -3
  123. package/dist/commonjs/lib/middlewares/dta.js +0 -14
  124. package/dist/commonjs/lib/middlewares/hsts.d.ts +0 -4
  125. package/dist/commonjs/lib/middlewares/hsts.js +0 -23
  126. package/dist/commonjs/lib/middlewares/index.d.ts +0 -13
  127. package/dist/commonjs/lib/middlewares/index.js +0 -28
  128. package/dist/commonjs/lib/middlewares/methodnoallow.d.ts +0 -3
  129. package/dist/commonjs/lib/middlewares/methodnoallow.js +0 -22
  130. package/dist/commonjs/lib/middlewares/noopen.d.ts +0 -4
  131. package/dist/commonjs/lib/middlewares/noopen.js +0 -17
  132. package/dist/commonjs/lib/middlewares/nosniff.d.ts +0 -4
  133. package/dist/commonjs/lib/middlewares/nosniff.js +0 -30
  134. package/dist/commonjs/lib/middlewares/referrerPolicy.d.ts +0 -4
  135. package/dist/commonjs/lib/middlewares/referrerPolicy.js +0 -36
  136. package/dist/commonjs/lib/middlewares/xframe.d.ts +0 -4
  137. package/dist/commonjs/lib/middlewares/xframe.js +0 -19
  138. package/dist/commonjs/lib/middlewares/xssProtection.d.ts +0 -4
  139. package/dist/commonjs/lib/middlewares/xssProtection.js +0 -16
  140. package/dist/commonjs/lib/utils.d.ts +0 -19
  141. package/dist/commonjs/lib/utils.js +0 -206
  142. package/dist/commonjs/package.json +0 -3
  143. package/dist/commonjs/types.d.ts +0 -10
  144. package/dist/commonjs/types.js +0 -5
  145. package/dist/esm/agent.d.ts +0 -6
  146. package/dist/esm/agent.js +0 -11
  147. package/dist/esm/app/extend/agent.d.ts +0 -5
  148. package/dist/esm/app/extend/agent.js +0 -8
  149. package/dist/esm/app/extend/application.d.ts +0 -16
  150. package/dist/esm/app/extend/application.js +0 -32
  151. package/dist/esm/app/extend/context.d.ts +0 -68
  152. package/dist/esm/app/extend/context.js +0 -244
  153. package/dist/esm/app/extend/helper.d.ts +0 -12
  154. package/dist/esm/app/extend/helper.js +0 -5
  155. package/dist/esm/app/extend/response.d.ts +0 -41
  156. package/dist/esm/app/extend/response.js +0 -82
  157. package/dist/esm/app/middleware/securities.d.ts +0 -4
  158. package/dist/esm/app/middleware/securities.js +0 -50
  159. package/dist/esm/app.d.ts +0 -6
  160. package/dist/esm/app.js +0 -26
  161. package/dist/esm/config/config.default.d.ts +0 -871
  162. package/dist/esm/config/config.default.js +0 -351
  163. package/dist/esm/config/config.local.d.ts +0 -5
  164. package/dist/esm/config/config.local.js +0 -8
  165. package/dist/esm/index.d.ts +0 -1
  166. package/dist/esm/index.js +0 -12
  167. package/dist/esm/lib/extend/safe_curl.d.ts +0 -16
  168. package/dist/esm/lib/extend/safe_curl.js +0 -25
  169. package/dist/esm/lib/helper/cliFilter.d.ts +0 -4
  170. package/dist/esm/lib/helper/cliFilter.js +0 -17
  171. package/dist/esm/lib/helper/escape.d.ts +0 -2
  172. package/dist/esm/lib/helper/escape.js +0 -3
  173. package/dist/esm/lib/helper/escapeShellArg.d.ts +0 -1
  174. package/dist/esm/lib/helper/escapeShellArg.js +0 -5
  175. package/dist/esm/lib/helper/escapeShellCmd.d.ts +0 -1
  176. package/dist/esm/lib/helper/escapeShellCmd.js +0 -14
  177. package/dist/esm/lib/helper/index.d.ts +0 -21
  178. package/dist/esm/lib/helper/index.js +0 -21
  179. package/dist/esm/lib/helper/shtml.d.ts +0 -2
  180. package/dist/esm/lib/helper/shtml.js +0 -70
  181. package/dist/esm/lib/helper/sjs.d.ts +0 -4
  182. package/dist/esm/lib/helper/sjs.js +0 -49
  183. package/dist/esm/lib/helper/sjson.d.ts +0 -1
  184. package/dist/esm/lib/helper/sjson.js +0 -39
  185. package/dist/esm/lib/helper/spath.d.ts +0 -5
  186. package/dist/esm/lib/helper/spath.js +0 -25
  187. package/dist/esm/lib/helper/surl.d.ts +0 -2
  188. package/dist/esm/lib/helper/surl.js +0 -30
  189. package/dist/esm/lib/middlewares/csp.d.ts +0 -4
  190. package/dist/esm/lib/middlewares/csp.js +0 -63
  191. package/dist/esm/lib/middlewares/csrf.d.ts +0 -4
  192. package/dist/esm/lib/middlewares/csrf.js +0 -37
  193. package/dist/esm/lib/middlewares/dta.d.ts +0 -3
  194. package/dist/esm/lib/middlewares/dta.js +0 -12
  195. package/dist/esm/lib/middlewares/hsts.d.ts +0 -4
  196. package/dist/esm/lib/middlewares/hsts.js +0 -21
  197. package/dist/esm/lib/middlewares/index.d.ts +0 -13
  198. package/dist/esm/lib/middlewares/index.js +0 -23
  199. package/dist/esm/lib/middlewares/methodnoallow.d.ts +0 -3
  200. package/dist/esm/lib/middlewares/methodnoallow.js +0 -20
  201. package/dist/esm/lib/middlewares/noopen.d.ts +0 -4
  202. package/dist/esm/lib/middlewares/noopen.js +0 -15
  203. package/dist/esm/lib/middlewares/nosniff.d.ts +0 -4
  204. package/dist/esm/lib/middlewares/nosniff.js +0 -28
  205. package/dist/esm/lib/middlewares/referrerPolicy.d.ts +0 -4
  206. package/dist/esm/lib/middlewares/referrerPolicy.js +0 -34
  207. package/dist/esm/lib/middlewares/xframe.d.ts +0 -4
  208. package/dist/esm/lib/middlewares/xframe.js +0 -17
  209. package/dist/esm/lib/middlewares/xssProtection.d.ts +0 -4
  210. package/dist/esm/lib/middlewares/xssProtection.js +0 -14
  211. package/dist/esm/lib/utils.d.ts +0 -19
  212. package/dist/esm/lib/utils.js +0 -194
  213. package/dist/esm/package.json +0 -3
  214. package/dist/esm/types.d.ts +0 -10
  215. package/dist/esm/types.js +0 -3
  216. package/dist/package.json +0 -4
  217. package/src/agent.ts +0 -14
  218. package/src/app/extend/agent.ts +0 -14
  219. package/src/app/extend/application.ts +0 -51
  220. package/src/app/extend/context.ts +0 -282
  221. package/src/app/extend/helper.ts +0 -5
  222. package/src/app/extend/response.ts +0 -95
  223. package/src/app/middleware/securities.ts +0 -63
  224. package/src/app.ts +0 -31
  225. package/src/config/config.default.ts +0 -379
  226. package/src/config/config.local.ts +0 -9
  227. package/src/index.ts +0 -12
  228. package/src/lib/extend/safe_curl.ts +0 -35
  229. package/src/lib/helper/cliFilter.ts +0 -20
  230. package/src/lib/helper/escape.ts +0 -3
  231. package/src/lib/helper/escapeShellArg.ts +0 -4
  232. package/src/lib/helper/escapeShellCmd.ts +0 -16
  233. package/src/lib/helper/index.ts +0 -21
  234. package/src/lib/helper/shtml.ts +0 -77
  235. package/src/lib/helper/sjs.ts +0 -57
  236. package/src/lib/helper/sjson.ts +0 -35
  237. package/src/lib/helper/spath.ts +0 -27
  238. package/src/lib/helper/surl.ts +0 -35
  239. package/src/lib/middlewares/csp.ts +0 -70
  240. package/src/lib/middlewares/csrf.ts +0 -44
  241. package/src/lib/middlewares/dta.ts +0 -13
  242. package/src/lib/middlewares/hsts.ts +0 -24
  243. package/src/lib/middlewares/index.ts +0 -23
  244. package/src/lib/middlewares/methodnoallow.ts +0 -23
  245. package/src/lib/middlewares/noopen.ts +0 -18
  246. package/src/lib/middlewares/nosniff.ts +0 -32
  247. package/src/lib/middlewares/referrerPolicy.ts +0 -39
  248. package/src/lib/middlewares/xframe.ts +0 -20
  249. package/src/lib/middlewares/xssProtection.ts +0 -17
  250. package/src/lib/utils.ts +0 -208
  251. package/src/types.ts +0 -16
  252. package/src/typings/index.d.ts +0 -4
@@ -0,0 +1,170 @@
1
+ import z from "zod";
2
+ import { Context } from "egg";
3
+
4
+ //#region src/config/config.default.ts
5
+ const CSRFSupportRequestItem = z.object({
6
+ path: z.instanceof(RegExp),
7
+ methods: z.array(z.string())
8
+ });
9
+ const LookupAddress = z.object({
10
+ address: z.string(),
11
+ family: z.number()
12
+ });
13
+ const LookupAddressAndStringArray = z.union([z.string(), LookupAddress]).array();
14
+ const SSRFCheckAddressFunction = z.function().args(z.union([
15
+ z.string(),
16
+ LookupAddress,
17
+ LookupAddressAndStringArray
18
+ ]), z.union([z.number(), z.string()]), z.string()).returns(z.boolean());
19
+ const SecurityMiddlewareName = z.enum([
20
+ "csrf",
21
+ "hsts",
22
+ "methodnoallow",
23
+ "noopen",
24
+ "nosniff",
25
+ "csp",
26
+ "xssProtection",
27
+ "xframe",
28
+ "dta"
29
+ ]);
30
+ /**
31
+ * (ctx) => boolean
32
+ */
33
+ const IgnoreOrMatchHandler = z.function().args(z.instanceof(Context)).returns(z.boolean());
34
+ const IgnoreOrMatch = z.union([
35
+ z.string(),
36
+ z.instanceof(RegExp),
37
+ IgnoreOrMatchHandler
38
+ ]);
39
+ const IgnoreOrMatchOption = z.union([IgnoreOrMatch, IgnoreOrMatch.array()]).optional();
40
+ /**
41
+ * security options
42
+ * @member Config#security
43
+ */
44
+ const SecurityConfig = z.object({
45
+ domainWhiteList: z.array(z.string()).default([]),
46
+ protocolWhiteList: z.array(z.string()).default([]),
47
+ defaultMiddleware: z.union([z.string(), z.array(SecurityMiddlewareName)]).default(SecurityMiddlewareName.options),
48
+ csrf: z.preprocess((val) => {
49
+ if (typeof val === "boolean") return { enable: val };
50
+ return val;
51
+ }, z.object({
52
+ match: IgnoreOrMatchOption,
53
+ ignore: IgnoreOrMatchOption,
54
+ enable: z.boolean().default(true),
55
+ type: z.enum([
56
+ "ctoken",
57
+ "referer",
58
+ "all",
59
+ "any"
60
+ ]).default("ctoken"),
61
+ ignoreJSON: z.boolean().default(false),
62
+ cookieName: z.union([z.string(), z.array(z.string())]).default("csrfToken"),
63
+ sessionName: z.string().default("csrfToken"),
64
+ headerName: z.string().default("x-csrf-token"),
65
+ bodyName: z.union([z.string(), z.array(z.string())]).default("_csrf"),
66
+ queryName: z.union([z.string(), z.array(z.string())]).default("_csrf"),
67
+ rotateWhenInvalid: z.boolean().default(false),
68
+ useSession: z.boolean().default(false),
69
+ cookieDomain: z.union([z.string(), z.function().args(z.instanceof(Context)).returns(z.string())]).optional(),
70
+ supportedRequests: z.array(CSRFSupportRequestItem).default([{
71
+ path: /^\//,
72
+ methods: [
73
+ "POST",
74
+ "PATCH",
75
+ "DELETE",
76
+ "PUT",
77
+ "CONNECT"
78
+ ]
79
+ }]),
80
+ refererWhiteList: z.array(z.string()).default([]),
81
+ cookieOptions: z.object({
82
+ signed: z.boolean(),
83
+ httpOnly: z.boolean(),
84
+ overwrite: z.boolean()
85
+ }).default({
86
+ signed: false,
87
+ httpOnly: false,
88
+ overwrite: true
89
+ })
90
+ }).default({})),
91
+ xframe: z.object({
92
+ match: IgnoreOrMatchOption,
93
+ ignore: IgnoreOrMatchOption,
94
+ enable: z.boolean().default(true),
95
+ value: z.string().default("SAMEORIGIN")
96
+ }).default({}),
97
+ hsts: z.object({
98
+ match: IgnoreOrMatchOption,
99
+ ignore: IgnoreOrMatchOption,
100
+ enable: z.boolean().default(false),
101
+ maxAge: z.number().default(365 * 24 * 3600),
102
+ includeSubdomains: z.boolean().default(false)
103
+ }).default({}),
104
+ methodnoallow: z.object({
105
+ match: IgnoreOrMatchOption,
106
+ ignore: IgnoreOrMatchOption,
107
+ enable: z.boolean().default(true)
108
+ }).default({}),
109
+ noopen: z.object({
110
+ match: IgnoreOrMatchOption,
111
+ ignore: IgnoreOrMatchOption,
112
+ enable: z.boolean().default(true)
113
+ }).default({}),
114
+ nosniff: z.object({
115
+ match: IgnoreOrMatchOption,
116
+ ignore: IgnoreOrMatchOption,
117
+ enable: z.boolean().default(true)
118
+ }).default({}),
119
+ xssProtection: z.object({
120
+ match: IgnoreOrMatchOption,
121
+ ignore: IgnoreOrMatchOption,
122
+ enable: z.boolean().default(true),
123
+ value: z.coerce.string().default("1; mode=block")
124
+ }).default({}),
125
+ csp: z.object({
126
+ match: IgnoreOrMatchOption,
127
+ ignore: IgnoreOrMatchOption,
128
+ enable: z.boolean().default(false),
129
+ policy: z.record(z.union([
130
+ z.string(),
131
+ z.array(z.string()),
132
+ z.boolean()
133
+ ])).default({}),
134
+ reportOnly: z.boolean().optional(),
135
+ supportIE: z.boolean().optional()
136
+ }).default({}),
137
+ referrerPolicy: z.object({
138
+ match: IgnoreOrMatchOption,
139
+ ignore: IgnoreOrMatchOption,
140
+ enable: z.boolean().default(false),
141
+ value: z.string().default("no-referrer-when-downgrade")
142
+ }).default({}),
143
+ dta: z.object({
144
+ match: IgnoreOrMatchOption,
145
+ ignore: IgnoreOrMatchOption,
146
+ enable: z.boolean().default(true)
147
+ }).default({}),
148
+ ssrf: z.object({
149
+ ipBlackList: z.array(z.string()).optional(),
150
+ ipExceptionList: z.array(z.string()).optional(),
151
+ hostnameExceptionList: z.array(z.string()).optional(),
152
+ checkAddress: SSRFCheckAddressFunction.optional()
153
+ }).default({}),
154
+ match: z.union([IgnoreOrMatch, IgnoreOrMatch.array()]).optional(),
155
+ ignore: z.union([IgnoreOrMatch, IgnoreOrMatch.array()]).optional(),
156
+ __protocolWhiteListSet: z.set(z.string()).optional().readonly()
157
+ });
158
+ const SecurityHelperOnTagAttrHandler = z.function().args(z.string(), z.string(), z.string(), z.boolean()).returns(z.union([z.string(), z.void()]));
159
+ const SecurityHelperConfig = z.object({ shtml: z.object({
160
+ whiteList: z.record(z.array(z.string())).optional(),
161
+ domainWhiteList: z.array(z.string()).optional(),
162
+ onTagAttr: SecurityHelperOnTagAttrHandler.optional()
163
+ }).default({}) });
164
+ var config_default_default = {
165
+ security: SecurityConfig.parse({}),
166
+ helper: SecurityHelperConfig.parse({})
167
+ };
168
+
169
+ //#endregion
170
+ export { LookupAddress, SecurityConfig, SecurityHelperConfig, SecurityMiddlewareName, config_default_default as default };
@@ -0,0 +1,6 @@
1
+ import { PartialEggConfig } from "egg";
2
+
3
+ //#region src/config/config.local.d.ts
4
+ declare const _default: PartialEggConfig;
5
+ //#endregion
6
+ export { _default as default };
@@ -0,0 +1,5 @@
1
+ //#region src/config/config.local.ts
2
+ var config_local_default = { security: { hsts: { enable: false } } };
3
+
4
+ //#endregion
5
+ export { config_local_default as default };
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import "./types.js";
2
+
3
+ export { };
@@ -0,0 +1,20 @@
1
+ import { SSRFCheckAddressFunction } from "../../config/config.default.js";
2
+ import * as egg10 from "egg";
3
+ import { EggApplicationCore } from "egg";
4
+
5
+ //#region src/lib/extend/safe_curl.d.ts
6
+ type HttpClient = EggApplicationCore['HttpClient'];
7
+ type HttpClientParameters = Parameters<HttpClient['prototype']['request']>;
8
+ type HttpClientRequestURL = HttpClientParameters[0];
9
+ type HttpClientOptions = HttpClientParameters[1] & {
10
+ checkAddress?: SSRFCheckAddressFunction;
11
+ };
12
+ type HttpClientResponse<T = any> = Awaited<ReturnType<HttpClient['prototype']['request']>> & {
13
+ data: T;
14
+ };
15
+ /**
16
+ * safe curl with ssrf protection
17
+ */
18
+ declare function safeCurlForApplication<T = any>(app: EggApplicationCore, url: HttpClientRequestURL, options?: HttpClientOptions): Promise<egg10.HttpClientResponse<T>>;
19
+ //#endregion
20
+ export { HttpClientOptions, HttpClientRequestURL, HttpClientResponse, safeCurlForApplication };
@@ -0,0 +1,19 @@
1
+ //#region src/lib/extend/safe_curl.ts
2
+ const SSRF_HTTPCLIENT = Symbol("SSRF_HTTPCLIENT");
3
+ /**
4
+ * safe curl with ssrf protection
5
+ */
6
+ async function safeCurlForApplication(app, url, options = {}) {
7
+ const ssrfConfig = app.config.security.ssrf;
8
+ if (ssrfConfig?.checkAddress) options.checkAddress = ssrfConfig.checkAddress;
9
+ else app.logger.warn("[@eggjs/security] please configure `config.security.ssrf` first");
10
+ if (ssrfConfig?.checkAddress) {
11
+ let httpClient = app[SSRF_HTTPCLIENT];
12
+ if (!httpClient) httpClient = app[SSRF_HTTPCLIENT] = app.createHttpClient({ checkAddress: ssrfConfig.checkAddress });
13
+ return await httpClient.request(url, options);
14
+ }
15
+ return await app.curl(url, options);
16
+ }
17
+
18
+ //#endregion
19
+ export { safeCurlForApplication };
@@ -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 as default };
@@ -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 as default };
@@ -0,0 +1,2 @@
1
+ import escapeHTML from "escape-html";
2
+ export { escapeHTML as default };
@@ -0,0 +1,7 @@
1
+ import escapeHTML from "escape-html";
2
+
3
+ //#region src/lib/helper/escape.ts
4
+ var escape_default = escapeHTML;
5
+
6
+ //#endregion
7
+ export { escape_default as default };
@@ -0,0 +1,4 @@
1
+ //#region src/lib/helper/escapeShellArg.d.ts
2
+ declare function escapeShellArg(text: string): string;
3
+ //#endregion
4
+ export { escapeShellArg as default };
@@ -0,0 +1,7 @@
1
+ //#region src/lib/helper/escapeShellArg.ts
2
+ function escapeShellArg(text) {
3
+ return "'" + ("" + text).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
4
+ }
5
+
6
+ //#endregion
7
+ export { escapeShellArg as default };
@@ -0,0 +1,4 @@
1
+ //#region src/lib/helper/escapeShellCmd.d.ts
2
+ declare function escapeShellCmd(text: string): string;
3
+ //#endregion
4
+ export { escapeShellCmd as default };
@@ -0,0 +1,15 @@
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 as default };
@@ -0,0 +1,24 @@
1
+ import cliFilter from "./cliFilter.js";
2
+ import escapeShellArg from "./escapeShellArg.js";
3
+ import escapeShellCmd from "./escapeShellCmd.js";
4
+ import shtml from "./shtml.js";
5
+ import escapeJavaScript from "./sjs.js";
6
+ import jsonEscape from "./sjson.js";
7
+ import pathFilter from "./spath.js";
8
+ import surl from "./surl.js";
9
+ import escapeHTML from "./escape.js";
10
+
11
+ //#region src/lib/helper/index.d.ts
12
+ declare const _default: {
13
+ cliFilter: typeof cliFilter;
14
+ escape: typeof escapeHTML;
15
+ escapeShellArg: typeof escapeShellArg;
16
+ escapeShellCmd: typeof escapeShellCmd;
17
+ shtml: typeof shtml;
18
+ sjs: typeof escapeJavaScript;
19
+ sjson: typeof jsonEscape;
20
+ spath: typeof pathFilter;
21
+ surl: typeof surl;
22
+ };
23
+ //#endregion
24
+ export { _default as default };
@@ -0,0 +1,25 @@
1
+ import cliFilter from "./cliFilter.js";
2
+ import escape_default from "./escape.js";
3
+ import escapeShellArg from "./escapeShellArg.js";
4
+ import escapeShellCmd from "./escapeShellCmd.js";
5
+ import shtml from "./shtml.js";
6
+ import escapeJavaScript from "./sjs.js";
7
+ import jsonEscape from "./sjson.js";
8
+ import pathFilter from "./spath.js";
9
+ import surl from "./surl.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 as default };
@@ -0,0 +1,6 @@
1
+ import { BaseContextClass } from "egg";
2
+
3
+ //#region src/lib/helper/shtml.d.ts
4
+ declare function shtml(this: BaseContextClass, val: string): string;
5
+ //#endregion
6
+ export { shtml as default };
@@ -0,0 +1,53 @@
1
+ import { getFromUrl, isSafeDomain } from "../utils.js";
2
+ import xss from "xss";
3
+
4
+ //#region src/lib/helper/shtml.ts
5
+ const BUILD_IN_ON_TAG_ATTR = Symbol("buildInOnTagAttr");
6
+ function shtml(val) {
7
+ if (typeof val !== "string") return val;
8
+ const securityOptions = this.ctx.securityOptions;
9
+ const shtmlConfig = {
10
+ ...this.app.config.helper.shtml,
11
+ ...securityOptions.shtml,
12
+ [BUILD_IN_ON_TAG_ATTR]: void 0
13
+ };
14
+ const domainWhiteList = this.app.config.security.domainWhiteList;
15
+ const app = this.app;
16
+ if (!shtmlConfig[BUILD_IN_ON_TAG_ATTR]) {
17
+ shtmlConfig[BUILD_IN_ON_TAG_ATTR] = (_tag, name, value, isWhiteAttr) => {
18
+ if (isWhiteAttr && (name === "href" || name === "src")) {
19
+ if (!value) return;
20
+ value = String(value);
21
+ if (value[0] === "/" || value[0] === "#") return;
22
+ const hostname = getFromUrl(value, "hostname");
23
+ if (!hostname) return;
24
+ if (!isSafeDomain(hostname, domainWhiteList)) if (shtmlConfig.domainWhiteList && shtmlConfig.domainWhiteList.length > 0) {
25
+ app.deprecate("[@eggjs/security/lib/helper/shtml] `config.helper.shtml.domainWhiteList` has been deprecate. Please use `config.security.domainWhiteList` instead.");
26
+ if (!isSafeDomain(hostname, shtmlConfig.domainWhiteList)) return "";
27
+ } else return "";
28
+ }
29
+ };
30
+ if (shtmlConfig.onTagAttr) {
31
+ const customOnTagAttrHandler = shtmlConfig.onTagAttr;
32
+ shtmlConfig.onTagAttr = function(tag, name, value, isWhiteAttr) {
33
+ const result = customOnTagAttrHandler.apply(this, [
34
+ tag,
35
+ name,
36
+ value,
37
+ isWhiteAttr
38
+ ]);
39
+ if (result !== void 0) return result;
40
+ return shtmlConfig[BUILD_IN_ON_TAG_ATTR].apply(this, [
41
+ tag,
42
+ name,
43
+ value,
44
+ isWhiteAttr
45
+ ]);
46
+ };
47
+ } else shtmlConfig.onTagAttr = shtmlConfig[BUILD_IN_ON_TAG_ATTR];
48
+ }
49
+ return xss(val, shtmlConfig);
50
+ }
51
+
52
+ //#endregion
53
+ export { shtml as default };
@@ -0,0 +1,7 @@
1
+ //#region src/lib/helper/sjs.d.ts
2
+ /**
3
+ * Escape JavaScript to \xHH format
4
+ */
5
+ declare function escapeJavaScript(text: string): string;
6
+ //#endregion
7
+ export { escapeJavaScript as default };
@@ -0,0 +1,36 @@
1
+ //#region src/lib/helper/sjs.ts
2
+ /**
3
+ * Escape JavaScript to \xHH format
4
+ */
5
+ const MATCH_VULNERABLE_REGEXP = /[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/;
6
+ const BASIC_ALPHABETS = new Set("abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
7
+ const map = {
8
+ " ": "\\t",
9
+ "\n": "\\n",
10
+ "\r": "\\r"
11
+ };
12
+ function escapeJavaScript(text) {
13
+ const str = "" + text;
14
+ const match = MATCH_VULNERABLE_REGEXP.exec(str);
15
+ if (!match) return str;
16
+ let res = "";
17
+ let index = 0;
18
+ let lastIndex = 0;
19
+ let ascii;
20
+ for (index = match.index; index < str.length; index++) {
21
+ ascii = str[index];
22
+ if (BASIC_ALPHABETS.has(ascii)) continue;
23
+ else if (map[ascii] === void 0) {
24
+ const code = ascii.charCodeAt(0);
25
+ if (code > 127) continue;
26
+ else map[ascii] = "\\x" + code.toString(16);
27
+ }
28
+ if (lastIndex !== index) res += str.substring(lastIndex, index);
29
+ lastIndex = index + 1;
30
+ res += map[ascii];
31
+ }
32
+ return lastIndex !== index ? res + str.substring(lastIndex, index) : res;
33
+ }
34
+
35
+ //#endregion
36
+ export { escapeJavaScript as default };
@@ -0,0 +1,4 @@
1
+ //#region src/lib/helper/sjson.d.ts
2
+ declare function jsonEscape(obj: any): string;
3
+ //#endregion
4
+ export { jsonEscape as default };
@@ -0,0 +1,32 @@
1
+ import escapeJavaScript from "./sjs.js";
2
+
3
+ //#region src/lib/helper/sjson.ts
4
+ /**
5
+ * escape json
6
+ * for output json in script
7
+ */
8
+ function sanitizeKey(obj) {
9
+ if (typeof obj !== "object") return obj;
10
+ if (Array.isArray(obj)) return obj;
11
+ if (obj === null) return null;
12
+ if (typeof obj === "boolean") return obj;
13
+ if (typeof obj === "number") return obj;
14
+ if (Buffer.isBuffer(obj)) return obj.toString();
15
+ for (const k in obj) {
16
+ const escapedK = escapeJavaScript(k);
17
+ if (escapedK !== k) {
18
+ obj[escapedK] = sanitizeKey(obj[k]);
19
+ obj[k] = void 0;
20
+ } else obj[k] = sanitizeKey(obj[k]);
21
+ }
22
+ return obj;
23
+ }
24
+ function jsonEscape(obj) {
25
+ return JSON.stringify(sanitizeKey(obj), (_k, v) => {
26
+ if (typeof v === "string") return escapeJavaScript(v);
27
+ return v;
28
+ });
29
+ }
30
+
31
+ //#endregion
32
+ export { jsonEscape as default };
@@ -0,0 +1,7 @@
1
+ import { BaseContextClass } from "egg";
2
+
3
+ //#region src/lib/helper/spath.d.ts
4
+
5
+ declare function pathFilter(this: BaseContextClass, path: string): string | null;
6
+ //#endregion
7
+ export { pathFilter as default };
@@ -0,0 +1,16 @@
1
+ //#region src/lib/helper/spath.ts
2
+ function pathFilter(path) {
3
+ if (typeof path !== "string") return path;
4
+ const pathSource = path;
5
+ while (path.indexOf("%") !== -1) try {
6
+ path = decodeURIComponent(path);
7
+ } catch {
8
+ if (process.env.NODE_ENV !== "production") this.ctx.coreLogger.warn("[@eggjs/security/lib/helper/spath] : decode file path %j failed.", path);
9
+ break;
10
+ }
11
+ if (path.indexOf("..") !== -1 || path[0] === "/") return null;
12
+ return pathSource;
13
+ }
14
+
15
+ //#endregion
16
+ export { pathFilter as default };
@@ -0,0 +1,6 @@
1
+ import { BaseContextClass } from "egg";
2
+
3
+ //#region src/lib/helper/surl.d.ts
4
+ declare function surl(this: BaseContextClass, val: string): string;
5
+ //#endregion
6
+ export { surl as default };
@@ -0,0 +1,25 @@
1
+ //#region src/lib/helper/surl.ts
2
+ const escapeMap = {
3
+ "\"": "&quot;",
4
+ "<": "&lt;",
5
+ ">": "&gt;",
6
+ "'": "&#x27;"
7
+ };
8
+ function surl(val) {
9
+ const protocolWhiteListSet = this.app.config.security.__protocolWhiteListSet;
10
+ if (typeof val !== "string") return val;
11
+ if (val[0] !== "/") {
12
+ const arr = val.split("://", 2);
13
+ const protocol = arr.length > 1 ? arr[0].toLowerCase() : "";
14
+ if (protocol === "" || !protocolWhiteListSet.has(protocol)) {
15
+ if (this.app.config.env === "local") this.ctx.coreLogger.warn("[@eggjs/security/surl] url: %j, protocol: %j, protocol is empty or not in white list, convert to empty string", val, protocol);
16
+ return "";
17
+ }
18
+ }
19
+ return val.replace(/["'<>]/g, (ch) => {
20
+ return escapeMap[ch];
21
+ });
22
+ }
23
+
24
+ //#endregion
25
+ export { surl as default };
@@ -0,0 +1,7 @@
1
+ import { SecurityConfig } from "../../config/config.default.js";
2
+ import { MiddlewareFunc } from "egg";
3
+
4
+ //#region src/lib/middlewares/csp.d.ts
5
+ declare const _default: (options: SecurityConfig["csp"]) => MiddlewareFunc;
6
+ //#endregion
7
+ export { _default as default };
@@ -0,0 +1,46 @@
1
+ import { checkIfIgnore } from "../utils.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 as default };
@@ -0,0 +1,7 @@
1
+ import { SecurityConfig } from "../../config/config.default.js";
2
+ import { MiddlewareFunc } from "egg";
3
+
4
+ //#region src/lib/middlewares/csrf.d.ts
5
+ declare const _default: (options: SecurityConfig["csrf"]) => MiddlewareFunc;
6
+ //#endregion
7
+ export { _default as default };
@@ -0,0 +1,33 @@
1
+ import { checkIfIgnore } from "../utils.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 as default };