@eggjs/security 5.0.0-beta.35 → 5.0.0-beta.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +9 -5
- package/dist/agent.js +14 -10
- package/dist/app/extend/agent.d.ts +8 -4
- package/dist/app/extend/agent.js +12 -8
- package/dist/app/extend/application.d.ts +11 -7
- package/dist/app/extend/application.js +32 -32
- package/dist/app/extend/context.d.ts +55 -51
- package/dist/app/extend/context.js +185 -240
- package/dist/app/extend/helper.d.ts +5 -2
- package/dist/app/extend/helper.js +8 -6
- package/dist/app/extend/response.d.ts +38 -34
- package/dist/app/extend/response.js +69 -82
- package/dist/app/middleware/securities.d.ts +5 -2
- package/dist/app/middleware/securities.js +38 -52
- package/dist/app.d.ts +9 -5
- package/dist/app.js +23 -25
- package/dist/config/config.default.d.ts +34 -45
- package/dist/config/config.default.js +158 -362
- package/dist/config/config.local.d.ts +6 -3
- package/dist/config/config.local.js +6 -8
- package/dist/index.d.ts +20 -16
- package/dist/index.js +24 -21
- package/dist/lib/extend/safe_curl.d.ts +16 -13
- package/dist/lib/extend/safe_curl.js +17 -23
- package/dist/lib/helper/cliFilter.d.ts +4 -4
- package/dist/lib/helper/cliFilter.js +16 -15
- package/dist/lib/helper/escape.d.ts +2 -2
- package/dist/lib/helper/escape.js +7 -3
- package/dist/lib/helper/escapeShellArg.d.ts +4 -1
- package/dist/lib/helper/escapeShellArg.js +6 -4
- package/dist/lib/helper/escapeShellCmd.d.ts +4 -1
- package/dist/lib/helper/escapeShellCmd.js +14 -13
- package/dist/lib/helper/index.d.ts +22 -19
- package/dist/lib/helper/index.js +19 -15
- package/dist/lib/helper/shtml.d.ts +6 -2
- package/dist/lib/helper/shtml.js +52 -68
- package/dist/lib/helper/sjs.d.ts +4 -4
- package/dist/lib/helper/sjs.js +31 -44
- package/dist/lib/helper/sjson.d.ts +4 -1
- package/dist/lib/helper/sjson.js +28 -35
- package/dist/lib/helper/spath.d.ts +7 -5
- package/dist/lib/helper/spath.js +15 -24
- package/dist/lib/helper/surl.d.ts +6 -2
- package/dist/lib/helper/surl.js +22 -27
- package/dist/lib/middlewares/csp.d.ts +6 -3
- package/dist/lib/middlewares/csp.js +43 -54
- package/dist/lib/middlewares/csrf.d.ts +6 -3
- package/dist/lib/middlewares/csrf.js +31 -35
- package/dist/lib/middlewares/dta.d.ts +5 -2
- package/dist/lib/middlewares/dta.js +11 -10
- package/dist/lib/middlewares/hsts.d.ts +6 -3
- package/dist/lib/middlewares/hsts.js +17 -19
- package/dist/lib/middlewares/index.d.ts +24 -21
- package/dist/lib/middlewares/index.js +26 -22
- package/dist/lib/middlewares/methodnoallow.d.ts +5 -2
- package/dist/lib/middlewares/methodnoallow.js +13 -18
- package/dist/lib/middlewares/noopen.d.ts +6 -3
- package/dist/lib/middlewares/noopen.js +14 -13
- package/dist/lib/middlewares/nosniff.d.ts +6 -3
- package/dist/lib/middlewares/nosniff.js +22 -24
- package/dist/lib/middlewares/referrerPolicy.d.ts +6 -3
- package/dist/lib/middlewares/referrerPolicy.js +27 -30
- package/dist/lib/middlewares/xframe.d.ts +6 -3
- package/dist/lib/middlewares/xframe.js +16 -15
- package/dist/lib/middlewares/xssProtection.d.ts +6 -3
- package/dist/lib/middlewares/xssProtection.js +15 -12
- package/dist/lib/utils.d.ts +22 -17
- package/dist/lib/utils.js +112 -177
- package/dist/types.d.ts +38 -36
- package/dist/types.js +1 -2
- package/package.json +31 -37
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { SSRFCheckAddressFunction } from "../../config/config.default.js";
|
|
2
|
+
import { EggApplicationCore } from "egg";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/extend/safe_curl.d.ts
|
|
5
|
+
type HttpClient = EggApplicationCore["HttpClient"];
|
|
6
|
+
type HttpClientParameters = Parameters<HttpClient["prototype"]["request"]>;
|
|
7
|
+
type HttpClientRequestURL = HttpClientParameters[0];
|
|
8
|
+
type HttpClientOptions = HttpClientParameters[1] & {
|
|
9
|
+
checkAddress?: SSRFCheckAddressFunction;
|
|
8
10
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
type HttpClientResponse<T = any> = Awaited<ReturnType<HttpClient["prototype"]["request"]>> & {
|
|
12
|
+
data: T;
|
|
11
13
|
};
|
|
12
14
|
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
* safe curl with ssrf protection
|
|
16
|
+
*/
|
|
17
|
+
declare function safeCurlForApplication<T = any>(app: EggApplicationCore, url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { HttpClientOptions, HttpClientRequestURL, HttpClientResponse, safeCurlForApplication };
|
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/lib/extend/safe_curl.ts
|
|
2
|
+
const SSRF_HTTPCLIENT = Symbol("SSRF_HTTPCLIENT");
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// use the new httpClient init with checkAddress
|
|
16
|
-
if (!httpClient) {
|
|
17
|
-
httpClient = app[SSRF_HTTPCLIENT] = app.createHttpClient({
|
|
18
|
-
checkAddress: ssrfConfig.checkAddress,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
return await httpClient.request(url, options);
|
|
22
|
-
}
|
|
23
|
-
return await app.curl(url, options);
|
|
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);
|
|
24
16
|
}
|
|
25
|
-
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { safeCurlForApplication };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
1
|
+
//#region src/lib/helper/cliFilter.d.ts
|
|
2
|
+
declare function cliFilter(text: string): string;
|
|
3
|
+
//#endregion
|
|
4
|
+
export { cliFilter as default };
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
//#region src/lib/helper/cliFilter.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const BASIC_ALPHABETS = new Set(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
return res;
|
|
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;
|
|
16
15
|
}
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { cliFilter as default };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import escapeHTML from
|
|
2
|
-
export default
|
|
1
|
+
import escapeHTML from "escape-html";
|
|
2
|
+
export { escapeHTML as default };
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import escapeHTML from
|
|
2
|
-
|
|
3
|
-
//#
|
|
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 };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
//#region src/lib/helper/escapeShellArg.ts
|
|
2
|
+
function escapeShellArg(text) {
|
|
3
|
+
return "'" + ("" + text).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
|
|
4
4
|
}
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
//#endregion
|
|
7
|
+
export { escapeShellArg as default };
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return res;
|
|
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;
|
|
13
12
|
}
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { escapeShellCmd as default };
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import cliFilter from
|
|
2
|
-
import
|
|
3
|
-
import escapeShellArg from
|
|
4
|
-
import escapeShellCmd from
|
|
5
|
-
import shtml from
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import surl from
|
|
1
|
+
import cliFilter from "./cliFilter.js";
|
|
2
|
+
import escapeHTML 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.d.ts
|
|
10
12
|
declare const helpers: {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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;
|
|
20
22
|
};
|
|
21
|
-
|
|
23
|
+
//#endregion
|
|
24
|
+
export { helpers as default };
|
package/dist/lib/helper/index.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import cliFilter from "./cliFilter.js";
|
|
2
|
-
import
|
|
2
|
+
import escape_default from "./escape.js";
|
|
3
3
|
import escapeShellArg from "./escapeShellArg.js";
|
|
4
4
|
import escapeShellCmd from "./escapeShellCmd.js";
|
|
5
5
|
import shtml from "./shtml.js";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
6
|
+
import escapeJavaScript from "./sjs.js";
|
|
7
|
+
import jsonEscape from "./sjson.js";
|
|
8
|
+
import pathFilter from "./spath.js";
|
|
9
9
|
import surl from "./surl.js";
|
|
10
|
+
|
|
11
|
+
//#region src/lib/helper/index.ts
|
|
10
12
|
const helpers = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
cliFilter,
|
|
14
|
+
escape: escape_default,
|
|
15
|
+
escapeShellArg,
|
|
16
|
+
escapeShellCmd,
|
|
17
|
+
shtml,
|
|
18
|
+
sjs: escapeJavaScript,
|
|
19
|
+
sjson: jsonEscape,
|
|
20
|
+
spath: pathFilter,
|
|
21
|
+
surl
|
|
20
22
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
var helper_default = helpers;
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { helper_default as default };
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
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 };
|
package/dist/lib/helper/shtml.js
CHANGED
|
@@ -1,69 +1,53 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
};
|
|
51
|
-
// avoid overriding user configuration 'onTagAttr'
|
|
52
|
-
if (shtmlConfig.onTagAttr) {
|
|
53
|
-
const customOnTagAttrHandler = shtmlConfig.onTagAttr;
|
|
54
|
-
shtmlConfig.onTagAttr = function (tag, name, value, isWhiteAttr) {
|
|
55
|
-
const result = customOnTagAttrHandler.apply(this, [tag, name, value, isWhiteAttr]);
|
|
56
|
-
if (result !== undefined) {
|
|
57
|
-
return result;
|
|
58
|
-
}
|
|
59
|
-
// fallback to build-in handler
|
|
60
|
-
return shtmlConfig[BUILD_IN_ON_TAG_ATTR].apply(this, [tag, name, value, isWhiteAttr]);
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
shtmlConfig.onTagAttr = shtmlConfig[BUILD_IN_ON_TAG_ATTR];
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return xss(val, shtmlConfig);
|
|
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);
|
|
68
50
|
}
|
|
69
|
-
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { shtml as default };
|
package/dist/lib/helper/sjs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
1
|
+
//#region src/lib/helper/sjs.d.ts
|
|
2
|
+
declare function escapeJavaScript(text: string): string;
|
|
3
|
+
//#endregion
|
|
4
|
+
export { escapeJavaScript as default };
|
package/dist/lib/helper/sjs.js
CHANGED
|
@@ -1,49 +1,36 @@
|
|
|
1
|
+
//#region src/lib/helper/sjs.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// escape \x00-\x7f
|
|
5
|
-
// except 0-9,A-Z,a-z(\x2f-\x3a \x40-\x5b \x60-\x7b)
|
|
6
|
-
// eslint-disable-next-line
|
|
3
|
+
* Escape JavaScript to \xHH format
|
|
4
|
+
*/
|
|
7
5
|
const MATCH_VULNERABLE_REGEXP = /[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/;
|
|
8
|
-
|
|
9
|
-
const BASIC_ALPHABETS = new Set('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''));
|
|
6
|
+
const BASIC_ALPHABETS = new Set("abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
|
|
10
7
|
const map = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
" ": "\\t",
|
|
9
|
+
"\n": "\\n",
|
|
10
|
+
"\r": "\\r"
|
|
14
11
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
else {
|
|
37
|
-
map[ascii] = '\\x' + code.toString(16);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (lastIndex !== index) {
|
|
42
|
-
res += str.substring(lastIndex, index);
|
|
43
|
-
}
|
|
44
|
-
lastIndex = index + 1;
|
|
45
|
-
res += map[ascii];
|
|
46
|
-
}
|
|
47
|
-
return lastIndex !== index ? res + str.substring(lastIndex, index) : res;
|
|
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;
|
|
48
33
|
}
|
|
49
|
-
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
export { escapeJavaScript as default };
|
package/dist/lib/helper/sjson.js
CHANGED
|
@@ -1,39 +1,32 @@
|
|
|
1
|
-
import
|
|
1
|
+
import escapeJavaScript from "./sjs.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/helper/sjson.ts
|
|
2
4
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
* escape json
|
|
6
|
+
* for output json in script
|
|
7
|
+
*/
|
|
6
8
|
function sanitizeKey(obj) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (escapedK !== k) {
|
|
22
|
-
obj[escapedK] = sanitizeKey(obj[k]);
|
|
23
|
-
obj[k] = undefined;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
obj[k] = sanitizeKey(obj[k]);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return 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;
|
|
30
23
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return v;
|
|
37
|
-
});
|
|
24
|
+
function jsonEscape(obj) {
|
|
25
|
+
return JSON.stringify(sanitizeKey(obj), (_k, v) => {
|
|
26
|
+
if (typeof v === "string") return escapeJavaScript(v);
|
|
27
|
+
return v;
|
|
28
|
+
});
|
|
38
29
|
}
|
|
39
|
-
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { jsonEscape as default };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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 };
|