@contrast/assess 1.18.0 → 1.20.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.
- package/LICENSE +1 -1
- package/lib/constants.js +26 -0
- package/lib/crypto-analysis/common.js +20 -0
- package/lib/crypto-analysis/index.js +44 -0
- package/lib/crypto-analysis/install/crypto.js +156 -0
- package/lib/crypto-analysis/install/math.js +104 -0
- package/lib/dataflow/index.js +1 -1
- package/lib/dataflow/propagation/common.js +1 -1
- package/lib/dataflow/propagation/index.js +1 -1
- package/lib/dataflow/propagation/install/JSON/index.js +1 -1
- package/lib/dataflow/propagation/install/JSON/parse-fn.js +1 -1
- package/lib/dataflow/propagation/install/JSON/parse.js +15 -14
- package/lib/dataflow/propagation/install/JSON/stringify.js +2 -2
- package/lib/dataflow/propagation/install/array-prototype-join.js +1 -1
- package/lib/dataflow/propagation/install/buffer.js +1 -1
- package/lib/dataflow/propagation/install/contrast-methods/add.js +1 -1
- package/lib/dataflow/propagation/install/contrast-methods/index.js +1 -1
- package/lib/dataflow/propagation/install/contrast-methods/number.js +4 -3
- package/lib/dataflow/propagation/install/contrast-methods/string.js +1 -1
- package/lib/dataflow/propagation/install/contrast-methods/tag.js +1 -1
- package/lib/dataflow/propagation/install/decode-uri-component.js +1 -1
- package/lib/dataflow/propagation/install/ejs/escape-xml.js +3 -3
- package/lib/dataflow/propagation/install/ejs/index.js +2 -1
- package/lib/dataflow/propagation/install/ejs/template.js +79 -0
- package/lib/dataflow/propagation/install/encode-uri.js +1 -1
- package/lib/dataflow/propagation/install/escape-html.js +1 -1
- package/lib/dataflow/propagation/install/escape.js +1 -1
- package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +1 -1
- package/lib/dataflow/propagation/install/isnumeric-0.js +3 -3
- package/lib/dataflow/propagation/install/joi/any.js +1 -1
- package/lib/dataflow/propagation/install/joi/boolean.js +1 -1
- package/lib/dataflow/propagation/install/joi/expression.js +1 -1
- package/lib/dataflow/propagation/install/joi/index.js +1 -1
- package/lib/dataflow/propagation/install/joi/keys.js +1 -1
- package/lib/dataflow/propagation/install/joi/number.js +1 -1
- package/lib/dataflow/propagation/install/joi/object.js +1 -1
- package/lib/dataflow/propagation/install/joi/string-schema.js +1 -1
- package/lib/dataflow/propagation/install/joi/utils.js +1 -1
- package/lib/dataflow/propagation/install/joi/values.js +1 -1
- package/lib/dataflow/propagation/install/mongoose/common.js +1 -1
- package/lib/dataflow/propagation/install/mongoose/index.js +1 -1
- package/lib/dataflow/propagation/install/mongoose/schema-map.js +1 -1
- package/lib/dataflow/propagation/install/mongoose/schema-mixed.js +1 -1
- package/lib/dataflow/propagation/install/mongoose/schema-string.js +1 -1
- package/lib/dataflow/propagation/install/mustache-escape.js +1 -1
- package/lib/dataflow/propagation/install/mysql-connection-escape.js +1 -1
- package/lib/dataflow/propagation/install/parse-int.js +3 -3
- package/lib/dataflow/propagation/install/path/basename.js +1 -1
- package/lib/dataflow/propagation/install/path/common.js +1 -1
- package/lib/dataflow/propagation/install/path/dirname.js +1 -1
- package/lib/dataflow/propagation/install/path/extname.js +1 -1
- package/lib/dataflow/propagation/install/path/format.js +1 -1
- package/lib/dataflow/propagation/install/path/index.js +1 -1
- package/lib/dataflow/propagation/install/path/join-and-resolve.js +1 -1
- package/lib/dataflow/propagation/install/path/normalize.js +1 -1
- package/lib/dataflow/propagation/install/path/parse.js +1 -1
- package/lib/dataflow/propagation/install/path/relative.js +1 -1
- package/lib/dataflow/propagation/install/path/toNamespacedPath.js +1 -1
- package/lib/dataflow/propagation/install/pug/index.js +3 -3
- package/lib/dataflow/propagation/install/pug-runtime-escape.js +1 -1
- package/lib/dataflow/propagation/install/querystring/escape.js +1 -1
- package/lib/dataflow/propagation/install/querystring/index.js +1 -1
- package/lib/dataflow/propagation/install/querystring/parse.js +1 -1
- package/lib/dataflow/propagation/install/querystring/stringify.js +1 -1
- package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +1 -1
- package/lib/dataflow/propagation/install/send.js +1 -1
- package/lib/dataflow/propagation/install/sequelize/index.js +1 -1
- package/lib/dataflow/propagation/install/sequelize/query-generator.js +1 -1
- package/lib/dataflow/propagation/install/sequelize/sql-string.js +1 -1
- package/lib/dataflow/propagation/install/sql-template-strings.js +1 -1
- package/lib/dataflow/propagation/install/string/concat.js +1 -1
- package/lib/dataflow/propagation/install/string/format-methods.js +1 -1
- package/lib/dataflow/propagation/install/string/html-methods.js +1 -1
- package/lib/dataflow/propagation/install/string/index.js +1 -1
- package/lib/dataflow/propagation/install/string/match-all.js +1 -1
- package/lib/dataflow/propagation/install/string/match.js +1 -1
- package/lib/dataflow/propagation/install/string/replace.js +1 -1
- package/lib/dataflow/propagation/install/string/slice.js +1 -1
- package/lib/dataflow/propagation/install/string/split.js +1 -1
- package/lib/dataflow/propagation/install/string/substring.js +1 -1
- package/lib/dataflow/propagation/install/string/trim.js +1 -1
- package/lib/dataflow/propagation/install/unescape.js +1 -1
- package/lib/dataflow/propagation/install/url/domain-parsers.js +1 -1
- package/lib/dataflow/propagation/install/url/index.js +1 -1
- package/lib/dataflow/propagation/install/url/parse.js +1 -1
- package/lib/dataflow/propagation/install/url/searchParams.js +1 -1
- package/lib/dataflow/propagation/install/url/url.js +1 -1
- package/lib/dataflow/propagation/install/util-format.js +10 -4
- package/lib/dataflow/propagation/install/validator/hooks.js +1 -1
- package/lib/dataflow/propagation/install/validator/index.js +1 -1
- package/lib/dataflow/propagation/install/validator/methods.js +1 -1
- package/lib/dataflow/sinks/common.js +1 -1
- package/lib/dataflow/sinks/index.js +1 -1
- package/lib/dataflow/sinks/install/child-process.js +21 -15
- package/lib/dataflow/sinks/install/eval.js +17 -15
- package/lib/dataflow/sinks/install/express/index.js +1 -1
- package/lib/dataflow/sinks/install/express/unvalidated-redirect.js +15 -9
- package/lib/dataflow/sinks/install/fastify/index.js +1 -1
- package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js +13 -6
- package/lib/dataflow/sinks/install/fs.js +8 -8
- package/lib/dataflow/sinks/install/function.js +9 -13
- package/lib/dataflow/sinks/install/http/index.js +1 -1
- package/lib/dataflow/sinks/install/http/request.js +17 -9
- package/lib/dataflow/sinks/install/http/server-response.js +12 -3
- package/lib/dataflow/sinks/install/koa/index.js +1 -1
- package/lib/dataflow/sinks/install/koa/unvalidated-redirect.js +16 -9
- package/lib/dataflow/sinks/install/libxmljs.js +16 -11
- package/lib/dataflow/sinks/install/marsdb.js +17 -12
- package/lib/dataflow/sinks/install/mongodb.js +32 -22
- package/lib/dataflow/sinks/install/mssql.js +21 -10
- package/lib/dataflow/sinks/install/mysql.js +16 -9
- package/lib/dataflow/sinks/install/node-serialize.js +16 -18
- package/lib/dataflow/sinks/install/postgres.js +18 -5
- package/lib/dataflow/sinks/install/sequelize.js +23 -17
- package/lib/dataflow/sinks/install/sqlite3.js +21 -8
- package/lib/dataflow/sinks/install/vm.js +20 -18
- package/lib/dataflow/sources/common.js +1 -1
- package/lib/dataflow/sources/handler.js +11 -10
- package/lib/dataflow/sources/index.js +2 -2
- package/lib/dataflow/sources/install/body-parser1.js +11 -13
- package/lib/dataflow/sources/install/{busboy1.js → busboy.js} +15 -15
- package/lib/dataflow/sources/install/cookie-parser1.js +7 -6
- package/lib/dataflow/sources/install/express/index.js +1 -1
- package/lib/dataflow/sources/install/express/params.js +9 -10
- package/lib/dataflow/sources/install/express/parsedUrl.js +1 -1
- package/lib/dataflow/sources/install/fastify/fastify.js +6 -7
- package/lib/dataflow/sources/install/fastify/index.js +1 -1
- package/lib/dataflow/sources/install/formidable1.js +8 -6
- package/lib/dataflow/sources/install/http.js +17 -45
- package/lib/dataflow/sources/install/koa/index.js +2 -1
- package/lib/dataflow/sources/install/koa/koa-bodyparsers.js +10 -9
- package/lib/dataflow/sources/install/koa/koa-multer.js +102 -0
- package/lib/dataflow/sources/install/koa/koa-routers.js +6 -8
- package/lib/dataflow/sources/install/koa/koa2.js +42 -38
- package/lib/dataflow/sources/install/multer1.js +26 -52
- package/lib/dataflow/sources/install/qs6.js +7 -6
- package/lib/dataflow/sources/install/querystring.js +5 -8
- package/lib/dataflow/tag-utils.js +1 -1
- package/lib/dataflow/tracker.js +1 -1
- package/lib/dataflow/utils/is-safe-content-type.js +1 -1
- package/lib/dataflow/utils/is-vulnerable.js +1 -1
- package/lib/event-factory.js +75 -26
- package/lib/get-policy.js +68 -0
- package/lib/get-source-context.js +62 -0
- package/lib/index.d.ts +64 -0
- package/lib/index.js +21 -20
- package/lib/make-source-context.js +78 -0
- package/lib/response-scanning/handlers/index.js +56 -29
- package/lib/response-scanning/handlers/utils.js +1 -1
- package/lib/response-scanning/index.js +1 -1
- package/lib/response-scanning/install/http.js +14 -8
- package/lib/rule-scopes.js +48 -0
- package/lib/session-configuration/common.js +1 -1
- package/lib/session-configuration/handlers.js +66 -47
- package/lib/session-configuration/index.js +3 -1
- package/lib/session-configuration/install/express-session.js +23 -26
- package/lib/session-configuration/install/fastify-cookie.js +110 -0
- package/lib/session-configuration/install/hapi.js +8 -11
- package/lib/session-configuration/install/koa.js +101 -0
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
19
|
const { patchType } = require('../common');
|
|
20
20
|
|
|
21
|
+
const inputType = InputType.MULTIPART_VALUE;
|
|
22
|
+
|
|
21
23
|
module.exports = (core) => {
|
|
22
24
|
const {
|
|
23
25
|
depHooks,
|
|
@@ -25,8 +27,8 @@ module.exports = (core) => {
|
|
|
25
27
|
logger,
|
|
26
28
|
assess: { dataflow: { sources } },
|
|
27
29
|
} = core;
|
|
28
|
-
const name = 'Formidable.IncomingForm.prototype.parse';
|
|
29
30
|
|
|
31
|
+
const name = 'Formidable.IncomingForm.prototype.parse';
|
|
30
32
|
|
|
31
33
|
// Patch `formidable`
|
|
32
34
|
function install() {
|
|
@@ -35,16 +37,16 @@ module.exports = (core) => {
|
|
|
35
37
|
name,
|
|
36
38
|
patchType,
|
|
37
39
|
pre(data) {
|
|
40
|
+
const { funcKey } = data;
|
|
38
41
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
39
|
-
const inputType = InputType.MULTIPART_VALUE;
|
|
40
42
|
|
|
41
43
|
if (!sourceContext) {
|
|
42
|
-
logger.error({ inputType,
|
|
44
|
+
logger.error({ inputType, funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
43
45
|
return;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
if (sourceContext.parsedBody) {
|
|
47
|
-
logger.trace({ inputType,
|
|
49
|
+
logger.trace({ inputType, funcKey }, 'values already tracked');
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -68,7 +70,7 @@ module.exports = (core) => {
|
|
|
68
70
|
});
|
|
69
71
|
sourceContext.parsedBody = true;
|
|
70
72
|
} catch (err) {
|
|
71
|
-
logger.error({ err, inputType,
|
|
73
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle source');
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -17,12 +17,17 @@
|
|
|
17
17
|
const { patchType } = require('../common');
|
|
18
18
|
const { toLowerCase, InputType } = require('@contrast/common');
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* @param {{
|
|
22
|
+
* assess: import('@contrast/assess').Assess,
|
|
23
|
+
* }} core
|
|
24
|
+
*/
|
|
25
|
+
module.exports = function (core) {
|
|
21
26
|
const {
|
|
22
|
-
|
|
27
|
+
assess: { dataflow, makeSourceContext },
|
|
23
28
|
instrumentation: { instrument },
|
|
24
|
-
assess: { dataflow },
|
|
25
29
|
patcher,
|
|
30
|
+
scopes,
|
|
26
31
|
} = core;
|
|
27
32
|
|
|
28
33
|
const logger = core.logger.child('contrast:assess');
|
|
@@ -34,19 +39,20 @@ module.exports = function(core) {
|
|
|
34
39
|
function around(next, data) {
|
|
35
40
|
const [type] = data.args;
|
|
36
41
|
|
|
37
|
-
if (type !== 'request')
|
|
38
|
-
return next();
|
|
39
|
-
}
|
|
42
|
+
if (type !== 'request') return next();
|
|
40
43
|
|
|
41
44
|
try {
|
|
42
45
|
const [, req, res] = data.args;
|
|
43
46
|
const store = scopes.sources.getStore();
|
|
44
47
|
|
|
45
48
|
if (!store) {
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
// this would indicate that sources did not install correctly
|
|
50
|
+
throw new Error('async request store not found');
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
store.assess = makeSourceContext(req, res);
|
|
54
|
+
if (!store.assess) return;
|
|
55
|
+
|
|
50
56
|
patcher.patch(res, 'writeHead', {
|
|
51
57
|
name: 'write-head',
|
|
52
58
|
patchType,
|
|
@@ -86,27 +92,7 @@ module.exports = function(core) {
|
|
|
86
92
|
});
|
|
87
93
|
}
|
|
88
94
|
|
|
89
|
-
let uriPath, queries;
|
|
90
|
-
const ix = req.url.indexOf('?');
|
|
91
|
-
|
|
92
|
-
if (ix >= 0) {
|
|
93
|
-
uriPath = req.url.slice(0, ix);
|
|
94
|
-
queries = req.url.slice(ix + 1);
|
|
95
|
-
} else {
|
|
96
|
-
uriPath = req.url;
|
|
97
|
-
queries = '';
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const headers = {};
|
|
101
95
|
const sourceName = 'ClientRequest';
|
|
102
|
-
|
|
103
|
-
store.assess = {
|
|
104
|
-
responseData: {},
|
|
105
|
-
sourceEventsCount: 0,
|
|
106
|
-
propagationEventsCount: 0,
|
|
107
|
-
findings: {},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
96
|
const sourceInfo = {
|
|
111
97
|
name: sourceName,
|
|
112
98
|
stacktraceOpts: {
|
|
@@ -135,30 +121,16 @@ module.exports = function(core) {
|
|
|
135
121
|
try {
|
|
136
122
|
dataflow.sources.handle(sourceData);
|
|
137
123
|
} catch (err) {
|
|
138
|
-
logger.error({ err, inputType,
|
|
124
|
+
logger.error({ err, inputType, sourceName }, 'unable to handle http source');
|
|
139
125
|
}
|
|
140
126
|
});
|
|
141
127
|
|
|
142
128
|
for (let i = 0; i < req.rawHeaders.length; i += 2) {
|
|
143
129
|
const header = toLowerCase(req.rawHeaders[i]);
|
|
144
|
-
headers[header] = req.rawHeaders[i + 1];
|
|
145
130
|
req.rawHeaders[i + 1] = req.headers[header];
|
|
146
131
|
}
|
|
147
|
-
|
|
148
|
-
const contentType = headers['content-type'] && toLowerCase(headers['content-type']);
|
|
149
|
-
|
|
150
|
-
store.assess.reqData = {
|
|
151
|
-
ip: req.socket.remoteAddress,
|
|
152
|
-
httpVersion: req.httpVersion,
|
|
153
|
-
method: req.method,
|
|
154
|
-
headers,
|
|
155
|
-
uriPath,
|
|
156
|
-
queries,
|
|
157
|
-
contentType,
|
|
158
|
-
};
|
|
159
|
-
|
|
160
132
|
} catch (err) {
|
|
161
|
-
logger.error({ err }, 'Error during
|
|
133
|
+
logger.error({ err, funcKey: data.funcKey }, 'Error during Assess request handling');
|
|
162
134
|
}
|
|
163
135
|
|
|
164
136
|
setImmediate(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -22,6 +22,7 @@ module.exports = function(core) {
|
|
|
22
22
|
|
|
23
23
|
require('./koa2')(core);
|
|
24
24
|
require('./koa-bodyparsers')(core);
|
|
25
|
+
require('./koa-multer')(core);
|
|
25
26
|
require('./koa-routers')(core);
|
|
26
27
|
|
|
27
28
|
koaSources.install = function install() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -28,25 +28,26 @@ module.exports = (core) => {
|
|
|
28
28
|
|
|
29
29
|
// Patch `koa-body` v4.x.x and `koa-bodyparser` v5.x.x packages
|
|
30
30
|
function install() {
|
|
31
|
-
['koa-body', 'koa-bodyparser'].forEach(
|
|
32
|
-
depHooks.resolve({ name
|
|
33
|
-
name
|
|
31
|
+
['koa-body', 'koa-bodyparser'].forEach((name) => {
|
|
32
|
+
depHooks.resolve({ name }, (koaBody) => patcher.patch(koaBody, {
|
|
33
|
+
name,
|
|
34
34
|
patchType,
|
|
35
35
|
post(data) {
|
|
36
36
|
data.result = patcher.patch(data.result, {
|
|
37
|
-
name
|
|
37
|
+
name,
|
|
38
38
|
patchType,
|
|
39
39
|
pre(data) {
|
|
40
|
+
const { funcKey } = data;
|
|
40
41
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
41
42
|
const [ctx, origNext] = data.args;
|
|
42
43
|
|
|
43
44
|
if (!sourceContext) {
|
|
44
|
-
logger.error({
|
|
45
|
+
logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
if (sourceContext.parsedBody) {
|
|
49
|
-
logger.trace({
|
|
50
|
+
logger.trace({ funcKey }, 'values already tracked');
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -61,7 +62,7 @@ module.exports = (core) => {
|
|
|
61
62
|
try {
|
|
62
63
|
sources.handle({
|
|
63
64
|
context: 'ctx.request.body',
|
|
64
|
-
name
|
|
65
|
+
name,
|
|
65
66
|
inputType,
|
|
66
67
|
stacktraceOpts: {
|
|
67
68
|
constructorOpt: contrastNext,
|
|
@@ -72,7 +73,7 @@ module.exports = (core) => {
|
|
|
72
73
|
|
|
73
74
|
sourceContext.parsedBody = !!Object.keys(ctx.request.body).length;
|
|
74
75
|
} catch (err) {
|
|
75
|
-
logger.error({ err, inputType,
|
|
76
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle Koa source');
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
await origNext(origErr);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
const { patchType } = require('../../common');
|
|
18
|
+
const { InputType } = require('@contrast/common');
|
|
19
|
+
|
|
20
|
+
module.exports = (core) => {
|
|
21
|
+
const {
|
|
22
|
+
depHooks,
|
|
23
|
+
logger,
|
|
24
|
+
patcher,
|
|
25
|
+
scopes,
|
|
26
|
+
assess: { dataflow: { sources } },
|
|
27
|
+
} = core;
|
|
28
|
+
|
|
29
|
+
function handler(req, constructorOpt) {
|
|
30
|
+
const sourceContext = scopes.sources.getStore()?.assess;
|
|
31
|
+
if (!sourceContext) return;
|
|
32
|
+
|
|
33
|
+
function handle(context, data, key) {
|
|
34
|
+
try {
|
|
35
|
+
sources.handle({
|
|
36
|
+
context,
|
|
37
|
+
data,
|
|
38
|
+
keys: [key],
|
|
39
|
+
name: 'multer',
|
|
40
|
+
inputType: InputType.BODY,
|
|
41
|
+
sourceContext,
|
|
42
|
+
stacktraceOpts: {
|
|
43
|
+
constructorOpt,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
} catch (err) {
|
|
47
|
+
logger.error({ err }, 'error handling Koa multer Assess dataflow %s.%s source', context, key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (req.file) {
|
|
52
|
+
handle('req', req, 'file');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (Array.isArray(req.files)) {
|
|
56
|
+
for (let i = 0; i < req.files.length; i++) {
|
|
57
|
+
handle('req.files', req.files[i], i);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (req.body && Object.keys(req.body).length) {
|
|
62
|
+
handle('req', req, 'body');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function install() {
|
|
67
|
+
['koa-multer', '@koa/multer'].forEach((name) => {
|
|
68
|
+
depHooks.resolve(
|
|
69
|
+
{ name }, (_export) => {
|
|
70
|
+
const origMulter = _export;
|
|
71
|
+
return patcher.patch(_export, {
|
|
72
|
+
name,
|
|
73
|
+
patchType,
|
|
74
|
+
post(data) {
|
|
75
|
+
const { args, hooked } = data;
|
|
76
|
+
const instance = origMulter.apply(this, args);
|
|
77
|
+
const origMake = instance._makeMiddleware;
|
|
78
|
+
instance._makeMiddleware = function _makeMiddleware(...args) {
|
|
79
|
+
const origMulterMiddleware = origMake.apply(this, args);
|
|
80
|
+
return function multerMiddleware(req, res, origNext) {
|
|
81
|
+
|
|
82
|
+
const next = function(...args) {
|
|
83
|
+
handler(req, hooked);
|
|
84
|
+
return origNext.apply(this, args);
|
|
85
|
+
};
|
|
86
|
+
return origMulterMiddleware.apply(this, [req, res, next]);
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
data.result = instance;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const koaMulterInstrumentation = sources.koaInstrumentation.koaMulter = {
|
|
98
|
+
install
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return koaMulterInstrumentation;
|
|
102
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -32,22 +32,20 @@ module.exports = (core) => {
|
|
|
32
32
|
depHooks.resolve(
|
|
33
33
|
{ name: router, file: 'lib/layer.js' },
|
|
34
34
|
(layer) => {
|
|
35
|
-
const name = `[${router}].layer.prototype`;
|
|
36
|
-
|
|
37
35
|
layer.prototype = patcher.patch(layer.prototype, 'params', {
|
|
38
|
-
name
|
|
36
|
+
name: `[${router}].layer.prototype`,
|
|
39
37
|
patchType,
|
|
40
|
-
post({ orig, hooked, result }) {
|
|
38
|
+
post({ orig, hooked, result, name, funcKey }) {
|
|
41
39
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
42
40
|
const inputType = InputType.URL_PARAMETER;
|
|
43
41
|
|
|
44
42
|
if (!sourceContext) {
|
|
45
|
-
logger.error({
|
|
43
|
+
logger.error({ inputType, funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
46
44
|
return;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
if (sourceContext.parsedParams) {
|
|
50
|
-
logger.trace({
|
|
48
|
+
logger.trace({ inputType, funcKey }, 'values already tracked');
|
|
51
49
|
return;
|
|
52
50
|
}
|
|
53
51
|
|
|
@@ -66,7 +64,7 @@ module.exports = (core) => {
|
|
|
66
64
|
|
|
67
65
|
sourceContext.parsedParams = Boolean(Object.keys(result).length);
|
|
68
66
|
} catch (err) {
|
|
69
|
-
logger.error({ err, inputType,
|
|
67
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle Koa source');
|
|
70
68
|
}
|
|
71
69
|
}
|
|
72
70
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
19
|
const { patchType } = require('../../common');
|
|
20
20
|
|
|
21
|
+
const inputType = InputType.QUERYSTRING;
|
|
22
|
+
|
|
21
23
|
/**
|
|
22
24
|
* Function that exports an install method to patch Koa framework with our instrumentation
|
|
23
25
|
* @param {Object} core - the core Contrast object in v5
|
|
@@ -36,58 +38,60 @@ module.exports = (core) => {
|
|
|
36
38
|
*/
|
|
37
39
|
function install() {
|
|
38
40
|
depHooks.resolve({ name: 'koa', version: '>=2.3.0' }, (Koa) => {
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const inputType = InputType.QUERYSTRING;
|
|
41
|
+
const createMiddleware = ({ name, funcKey }) => {
|
|
42
|
+
const contrastStartMiddleware = function contrastStartMiddleware(ctx, next) {
|
|
43
|
+
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return next();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// We check the contents mainly to trigger the getter for `ctx.query`
|
|
50
|
-
// that is eventually set up by `koa-qs`
|
|
51
|
-
if (ctx.query) {
|
|
52
|
-
if (sourceContext.parsedQuery) {
|
|
53
|
-
logger.trace({ name, inputType }, 'values already tracked');
|
|
45
|
+
if (!sourceContext) {
|
|
46
|
+
logger.error({ inputType, funcKey }, 'unable to handle Koa source. Missing `sourceContext`');
|
|
54
47
|
return next();
|
|
55
48
|
}
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
inputType,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
50
|
+
// We check the contents mainly to trigger the getter for `ctx.query`
|
|
51
|
+
// that is eventually set up by `koa-qs`
|
|
52
|
+
if (ctx.query) {
|
|
53
|
+
if (sourceContext.parsedQuery) {
|
|
54
|
+
logger.trace({ inputType, funcKey }, 'values already tracked');
|
|
55
|
+
return next();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
sources.handle({
|
|
60
|
+
context: 'ctx.query',
|
|
61
|
+
data: ctx.query,
|
|
62
|
+
inputType,
|
|
63
|
+
name,
|
|
64
|
+
stacktraceOpts: {
|
|
65
|
+
constructorOpt: contrastStartMiddleware,
|
|
66
|
+
},
|
|
67
|
+
sourceContext
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
sourceContext.parsedQuery = true;
|
|
71
|
+
} catch (err) {
|
|
72
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle Koa source');
|
|
73
|
+
}
|
|
72
74
|
}
|
|
73
|
-
}
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
return next();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// mark these middleware as ours
|
|
80
|
+
contrastStartMiddleware._isContrastStartMiddleware = true;
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
return contrastStartMiddleware;
|
|
83
|
+
};
|
|
80
84
|
|
|
81
85
|
patcher.patch(Koa.prototype, 'use', {
|
|
82
86
|
name: 'Koa.Application',
|
|
83
87
|
patchType,
|
|
84
|
-
pre({ obj: app }) {
|
|
88
|
+
pre({ obj: app, name, funcKey }) {
|
|
85
89
|
// if not already inserted, insert the initial middleware.
|
|
86
90
|
if (
|
|
87
91
|
app.middleware &&
|
|
88
|
-
|
|
92
|
+
(!app.middleware[0] || !app.middleware[0]._isContrastStartMiddleware)
|
|
89
93
|
) {
|
|
90
|
-
app.middleware.
|
|
94
|
+
app.middleware.unshift(createMiddleware({ name, funcKey }));
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -23,36 +23,20 @@ module.exports = (core) => {
|
|
|
23
23
|
depHooks,
|
|
24
24
|
patcher,
|
|
25
25
|
logger,
|
|
26
|
-
assess,
|
|
27
|
-
scopes
|
|
26
|
+
assess: { dataflow: { sources } },
|
|
27
|
+
scopes,
|
|
28
28
|
} = core;
|
|
29
29
|
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
context: 'req',
|
|
34
|
-
data: req,
|
|
35
|
-
keys: ['file'],
|
|
36
|
-
name: 'multer',
|
|
37
|
-
inputType: InputType.BODY,
|
|
38
|
-
sourceContext,
|
|
39
|
-
stacktraceOpts: {
|
|
40
|
-
constructorOpt,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
} catch (err) {
|
|
44
|
-
logger.error({ err }, 'error handling multer Assess dataflow req.file source');
|
|
45
|
-
}
|
|
46
|
-
}
|
|
30
|
+
function handler(req, constructorOpt) {
|
|
31
|
+
const sourceContext = scopes.sources.getStore()?.assess;
|
|
32
|
+
if (!sourceContext) return;
|
|
47
33
|
|
|
48
|
-
|
|
49
|
-
let i;
|
|
50
|
-
for (i = 0; i < req.files.length; i++) {
|
|
34
|
+
function handle(context, data, key) {
|
|
51
35
|
try {
|
|
52
|
-
|
|
53
|
-
context
|
|
54
|
-
data
|
|
55
|
-
keys: [
|
|
36
|
+
sources.handle({
|
|
37
|
+
context,
|
|
38
|
+
data,
|
|
39
|
+
keys: [key],
|
|
56
40
|
name: 'multer',
|
|
57
41
|
inputType: InputType.BODY,
|
|
58
42
|
sourceContext,
|
|
@@ -61,26 +45,22 @@ module.exports = (core) => {
|
|
|
61
45
|
},
|
|
62
46
|
});
|
|
63
47
|
} catch (err) {
|
|
64
|
-
logger.error({ err }, 'error handling multer Assess dataflow
|
|
48
|
+
logger.error({ err }, 'error handling multer Assess dataflow %s.%s source', context, key);
|
|
65
49
|
}
|
|
66
50
|
}
|
|
67
|
-
}
|
|
68
51
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
});
|
|
82
|
-
} catch (err) {
|
|
83
|
-
logger.error({ err }, 'error handling multer Assess dataflow req.body source');
|
|
52
|
+
if (req.file) {
|
|
53
|
+
handle('req', req, 'file');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (Array.isArray(req.files)) {
|
|
57
|
+
for (let i = 0; i < req.files.length; i++) {
|
|
58
|
+
handle('req.files', req.files[i], i);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (req.body && Object.keys(req.body).length) {
|
|
63
|
+
handle('req', req, 'body');
|
|
84
64
|
}
|
|
85
65
|
}
|
|
86
66
|
|
|
@@ -97,14 +77,8 @@ module.exports = (core) => {
|
|
|
97
77
|
patchType,
|
|
98
78
|
pre(data) {
|
|
99
79
|
const [req, , next, hooked] = data.args;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (!sourceContext) return;
|
|
103
|
-
|
|
104
|
-
data.args[2] = wrap(function (...args) {
|
|
105
|
-
if (req.file) handleFile(sourceContext, hooked, req);
|
|
106
|
-
if (Array.isArray(req.files)) handleFiles(sourceContext, hooked, req);
|
|
107
|
-
if (req.body && Object.keys(req.body).length) handleBody(sourceContext, hooked, req.body);
|
|
80
|
+
data.args[2] = scopes.wrap(function (...args) {
|
|
81
|
+
handler(req, hooked);
|
|
108
82
|
next(...args);
|
|
109
83
|
});
|
|
110
84
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright:
|
|
2
|
+
* Copyright: 2024 Contrast Security, Inc
|
|
3
3
|
* Contact: support@contrastsecurity.com
|
|
4
4
|
* License: Commercial
|
|
5
5
|
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
19
|
const { patchType } = require('../common');
|
|
20
20
|
|
|
21
|
+
const inputType = InputType.QUERYSTRING;
|
|
22
|
+
|
|
21
23
|
module.exports = (core) => {
|
|
22
24
|
const {
|
|
23
25
|
depHooks,
|
|
@@ -33,17 +35,16 @@ module.exports = (core) => {
|
|
|
33
35
|
(qs) => patcher.patch(qs, 'parse', {
|
|
34
36
|
name,
|
|
35
37
|
patchType,
|
|
36
|
-
post({ args, hooked, orig, result }) {
|
|
38
|
+
post({ args, hooked, orig, result, funcKey }) {
|
|
37
39
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
38
|
-
const inputType = InputType.QUERYSTRING;
|
|
39
40
|
|
|
40
41
|
if (!sourceContext) {
|
|
41
|
-
logger.error({ inputType,
|
|
42
|
+
logger.error({ inputType, funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (sourceContext.parsedQuery) {
|
|
46
|
-
logger.trace({ inputType,
|
|
47
|
+
logger.trace({ inputType, funcKey }, 'values already tracked');
|
|
47
48
|
return;
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -67,7 +68,7 @@ module.exports = (core) => {
|
|
|
67
68
|
|
|
68
69
|
sourceContext.parsedQuery = true;
|
|
69
70
|
} catch (err) {
|
|
70
|
-
logger.error({ err, inputType,
|
|
71
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle source');
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
}
|