@contrast/assess 1.19.0 → 1.20.1
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 +1 -1
- package/lib/crypto-analysis/common.js +1 -1
- package/lib/crypto-analysis/index.js +1 -1
- package/lib/crypto-analysis/install/crypto.js +8 -3
- package/lib/crypto-analysis/install/math.js +8 -3
- 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 +3 -3
- package/lib/dataflow/propagation/install/JSON/stringify.js +1 -1
- 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 +1 -1
- package/lib/dataflow/propagation/install/ejs/index.js +1 -1
- package/lib/dataflow/propagation/install/ejs/template.js +7 -5
- 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 +2 -2
- 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 +1 -1
- 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 +1 -1
- package/lib/dataflow/sinks/install/eval.js +1 -1
- package/lib/dataflow/sinks/install/express/index.js +1 -1
- package/lib/dataflow/sinks/install/express/unvalidated-redirect.js +1 -1
- package/lib/dataflow/sinks/install/fastify/index.js +1 -1
- package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js +1 -1
- package/lib/dataflow/sinks/install/fs.js +1 -1
- package/lib/dataflow/sinks/install/function.js +1 -1
- package/lib/dataflow/sinks/install/http/index.js +1 -1
- package/lib/dataflow/sinks/install/http/request.js +1 -1
- package/lib/dataflow/sinks/install/http/server-response.js +1 -1
- package/lib/dataflow/sinks/install/koa/index.js +1 -1
- package/lib/dataflow/sinks/install/koa/unvalidated-redirect.js +1 -1
- package/lib/dataflow/sinks/install/libxmljs.js +1 -1
- package/lib/dataflow/sinks/install/marsdb.js +4 -4
- package/lib/dataflow/sinks/install/mongodb.js +7 -7
- package/lib/dataflow/sinks/install/mssql.js +1 -1
- package/lib/dataflow/sinks/install/mysql.js +1 -1
- package/lib/dataflow/sinks/install/node-serialize.js +1 -1
- package/lib/dataflow/sinks/install/postgres.js +1 -1
- package/lib/dataflow/sinks/install/sequelize.js +7 -8
- package/lib/dataflow/sinks/install/sqlite3.js +1 -1
- package/lib/dataflow/sinks/install/vm.js +1 -1
- 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 +4 -4
- package/lib/dataflow/sources/install/koa/index.js +1 -1
- package/lib/dataflow/sources/install/koa/koa-bodyparsers.js +10 -9
- package/lib/dataflow/sources/install/koa/koa-multer.js +1 -1
- 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 +1 -1
- package/lib/dataflow/sources/install/qs6.js +7 -6
- package/lib/dataflow/sources/install/querystring.js +4 -4
- 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 +35 -33
- package/lib/get-policy.js +1 -1
- package/lib/get-source-context.js +1 -1
- package/lib/index.d.ts +16 -2
- package/lib/index.js +1 -1
- package/lib/make-source-context.js +6 -2
- package/lib/response-scanning/handlers/index.js +1 -1
- package/lib/response-scanning/handlers/utils.js +1 -1
- package/lib/response-scanning/index.js +1 -1
- package/lib/response-scanning/install/http.js +1 -1
- package/lib/rule-scopes.js +1 -1
- package/lib/session-configuration/common.js +1 -1
- package/lib/session-configuration/handlers.js +67 -49
- package/lib/session-configuration/index.js +3 -1
- package/lib/session-configuration/install/express-session.js +15 -24
- 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 +1 -1
|
@@ -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,7 +22,7 @@ const {
|
|
|
22
22
|
join,
|
|
23
23
|
} = require('@contrast/common');
|
|
24
24
|
|
|
25
|
-
module.exports = function(core) {
|
|
25
|
+
module.exports = function (core) {
|
|
26
26
|
const {
|
|
27
27
|
assess: {
|
|
28
28
|
eventFactory,
|
|
@@ -33,9 +33,10 @@ module.exports = function(core) {
|
|
|
33
33
|
},
|
|
34
34
|
config,
|
|
35
35
|
createSnapshot,
|
|
36
|
-
logger,
|
|
37
36
|
} = core;
|
|
38
37
|
|
|
38
|
+
const logger = core.logger.child({ name: 'contrast:sources' });
|
|
39
|
+
|
|
39
40
|
const emptyStack = Object.freeze([]);
|
|
40
41
|
|
|
41
42
|
sources.createTags = function createTags({ inputType, fieldName = '', value }) {
|
|
@@ -55,13 +56,13 @@ module.exports = function(core) {
|
|
|
55
56
|
return tags;
|
|
56
57
|
};
|
|
57
58
|
|
|
58
|
-
sources.createStacktrace = function(stacktraceOpts) {
|
|
59
|
+
sources.createStacktrace = function (stacktraceOpts) {
|
|
59
60
|
return config.assess.stacktraces === 'NONE'
|
|
60
61
|
? emptyStack
|
|
61
62
|
: createSnapshot(stacktraceOpts)();
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
sources.handle = function({
|
|
65
|
+
sources.handle = function ({
|
|
65
66
|
context,
|
|
66
67
|
keys,
|
|
67
68
|
name,
|
|
@@ -73,7 +74,7 @@ module.exports = function(core) {
|
|
|
73
74
|
if (!data) return;
|
|
74
75
|
|
|
75
76
|
if (!sourceContext) {
|
|
76
|
-
|
|
77
|
+
logger.trace({ inputType, sourceName: name }, 'skipping assess source handling - no request context');
|
|
77
78
|
return null;
|
|
78
79
|
}
|
|
79
80
|
|
|
@@ -119,7 +120,7 @@ module.exports = function(core) {
|
|
|
119
120
|
const pathName = join(path, '.');
|
|
120
121
|
|
|
121
122
|
if (sourceContext.sourceEventsCount >= max) {
|
|
122
|
-
|
|
123
|
+
logger.trace({ inputType, sourceName: name }, 'exiting assess source handling - %s max events exceeded', max);
|
|
123
124
|
return true;
|
|
124
125
|
}
|
|
125
126
|
|
|
@@ -136,13 +137,13 @@ module.exports = function(core) {
|
|
|
136
137
|
|
|
137
138
|
const event = createEvent({ pathName, value, fieldName });
|
|
138
139
|
if (!event) {
|
|
139
|
-
|
|
140
|
+
logger.warn({ inputType, sourceName: name, pathName, value }, 'unable to create source event');
|
|
140
141
|
return;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
const { extern } = tracker.track(value, event);
|
|
144
145
|
if (extern) {
|
|
145
|
-
logger.trace({ extern, fieldName, name, inputType }, 'tracked');
|
|
146
|
+
logger.trace({ extern, fieldName, sourceName: name, inputType }, 'tracked');
|
|
146
147
|
obj[fieldName] = extern;
|
|
147
148
|
|
|
148
149
|
sourceContext.sourceEventsCount++;
|
|
@@ -152,7 +153,7 @@ module.exports = function(core) {
|
|
|
152
153
|
if (event) {
|
|
153
154
|
tracker.track(value, event);
|
|
154
155
|
} else {
|
|
155
|
-
|
|
156
|
+
logger.warn({ inputType, sourceName: name, pathName, value }, 'unable to create source event');
|
|
156
157
|
}
|
|
157
158
|
}
|
|
158
159
|
});
|
|
@@ -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
|
|
|
@@ -26,7 +26,7 @@ module.exports = function (core) {
|
|
|
26
26
|
require('./install/fastify')(core);
|
|
27
27
|
require('./install/koa')(core);
|
|
28
28
|
require('./install/body-parser1')(core);
|
|
29
|
-
require('./install/
|
|
29
|
+
require('./install/busboy')(core);
|
|
30
30
|
require('./install/cookie-parser1')(core);
|
|
31
31
|
require('./install/formidable1')(core);
|
|
32
32
|
require('./install/http')(core);
|
|
@@ -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
|
|
|
@@ -29,23 +29,23 @@ const INPUT_TYPES = {
|
|
|
29
29
|
module.exports = function init(core) {
|
|
30
30
|
const { assess, depHooks, logger, patcher, scopes } = core;
|
|
31
31
|
|
|
32
|
-
const
|
|
32
|
+
const preHook = (data) => {
|
|
33
33
|
const [req, , next] = data.args;
|
|
34
34
|
data.args[2] = scopes.wrap(function contrastNext(...args) {
|
|
35
35
|
const sourceContext = scopes.sources.getStore()?.assess;
|
|
36
36
|
|
|
37
37
|
if (!sourceContext) {
|
|
38
|
-
logger.error({
|
|
38
|
+
logger.error({ funcKey: data.funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
39
39
|
return next(...args);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
if (sourceContext.parsedBody) {
|
|
43
|
-
logger.trace({
|
|
43
|
+
logger.trace({ funcKey: data.funcKey }, 'values already tracked');
|
|
44
44
|
return next(...args);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// when using a specific parser, we know the input type.
|
|
48
|
-
let inputType = INPUT_TYPES[name];
|
|
48
|
+
let inputType = INPUT_TYPES[data.name];
|
|
49
49
|
// when using `bodyParser()`, determine input type by content type.
|
|
50
50
|
if (!inputType) {
|
|
51
51
|
inputType = req.headers?.['content-type']?.includes('json')
|
|
@@ -71,7 +71,7 @@ module.exports = function init(core) {
|
|
|
71
71
|
assess.dataflow.sources.handle({
|
|
72
72
|
context,
|
|
73
73
|
data: _data,
|
|
74
|
-
name,
|
|
74
|
+
name: data.name,
|
|
75
75
|
keys,
|
|
76
76
|
inputType,
|
|
77
77
|
sourceContext,
|
|
@@ -82,7 +82,7 @@ module.exports = function init(core) {
|
|
|
82
82
|
|
|
83
83
|
sourceContext.parsedBody = !!Object.keys(_data).length;
|
|
84
84
|
} catch (err) {
|
|
85
|
-
logger.error({
|
|
85
|
+
logger.error({ err, funcKey: data.funcKey }, 'unable to handle source');
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
return next(...args);
|
|
@@ -99,11 +99,10 @@ module.exports = function init(core) {
|
|
|
99
99
|
name: 'body-parser',
|
|
100
100
|
patchType,
|
|
101
101
|
post(data) {
|
|
102
|
-
const name = 'body-parser.bodyParser';
|
|
103
102
|
data.result = patcher.patch(data.result, {
|
|
104
|
-
name,
|
|
103
|
+
name: 'body-parser.bodyParser',
|
|
105
104
|
patchType,
|
|
106
|
-
pre:
|
|
105
|
+
pre: preHook,
|
|
107
106
|
});
|
|
108
107
|
},
|
|
109
108
|
});
|
|
@@ -113,11 +112,10 @@ module.exports = function init(core) {
|
|
|
113
112
|
name: `body-parser.${method}`,
|
|
114
113
|
patchType,
|
|
115
114
|
post(data) {
|
|
116
|
-
const name = `body-parser.${method}.${method}Parser`;
|
|
117
115
|
data.result = patcher.patch(data.result, {
|
|
118
|
-
name
|
|
116
|
+
name: `body-parser.${method}.${method}Parser`,
|
|
119
117
|
patchType,
|
|
120
|
-
pre:
|
|
118
|
+
pre: preHook
|
|
121
119
|
});
|
|
122
120
|
},
|
|
123
121
|
});
|
|
@@ -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,9 @@
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
19
|
const { patchType } = require('../common');
|
|
20
20
|
|
|
21
|
+
const inputType = InputType.MULTIPART_VALUE;
|
|
22
|
+
const name = 'busboy';
|
|
23
|
+
|
|
21
24
|
module.exports = (core) => {
|
|
22
25
|
const {
|
|
23
26
|
depHooks,
|
|
@@ -26,21 +29,18 @@ module.exports = (core) => {
|
|
|
26
29
|
assess: { dataflow: { sources } },
|
|
27
30
|
} = core;
|
|
28
31
|
|
|
29
|
-
const name = 'busboy';
|
|
30
|
-
|
|
31
32
|
function createPreHook(finalEventName) {
|
|
32
|
-
return function(data) {
|
|
33
|
-
const { orig, hooked } = data;
|
|
33
|
+
return function (data) {
|
|
34
|
+
const { orig, hooked, funcKey } = data;
|
|
34
35
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
35
|
-
const inputType = InputType.MULTIPART_VALUE;
|
|
36
36
|
|
|
37
37
|
if (!sourceContext) {
|
|
38
|
-
logger.error({ inputType,
|
|
38
|
+
logger.error({ inputType, funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
if (sourceContext.parsedBody) {
|
|
43
|
-
logger.trace({ inputType,
|
|
43
|
+
logger.trace({ inputType, funcKey }, 'values already tracked');
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -67,7 +67,7 @@ module.exports = (core) => {
|
|
|
67
67
|
data.args[2] = obj[fieldName];
|
|
68
68
|
sourceContext.busboyParsedBody = true;
|
|
69
69
|
} catch (err) {
|
|
70
|
-
logger.error({ err, inputType,
|
|
70
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle source');
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -88,8 +88,8 @@ module.exports = (core) => {
|
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
depHooks.resolve({ name, version: '>=1.0.0' }, (busboy) =>
|
|
92
|
-
busboy, {
|
|
91
|
+
depHooks.resolve({ name, version: '>=1.0.0' }, (busboy) =>
|
|
92
|
+
patcher.patch(busboy, {
|
|
93
93
|
name,
|
|
94
94
|
patchType,
|
|
95
95
|
post(data) {
|
|
@@ -99,14 +99,14 @@ module.exports = (core) => {
|
|
|
99
99
|
pre: createPreHook('close')
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
|
-
}
|
|
103
|
-
)
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
const
|
|
106
|
+
const busboyInstrumentation = sources.busboyInstrumentation = {
|
|
107
107
|
install
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
-
return
|
|
110
|
+
return busboyInstrumentation;
|
|
111
111
|
};
|
|
112
112
|
|
|
@@ -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
|
|
|
@@ -36,17 +36,18 @@ module.exports = function init(core) {
|
|
|
36
36
|
name,
|
|
37
37
|
patchType,
|
|
38
38
|
pre(data) {
|
|
39
|
+
const { funcKey } = data;
|
|
39
40
|
const [req, , next] = data.args;
|
|
40
41
|
data.args[2] = function contrastNext(...args) {
|
|
41
42
|
const sourceContext = scopes.sources.getStore()?.assess;
|
|
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.parsedCookies) {
|
|
49
|
-
logger.trace({
|
|
50
|
+
logger.trace({ funcKey }, 'cookies already tracked');
|
|
50
51
|
} else if (req.cookies) {
|
|
51
52
|
try {
|
|
52
53
|
assess.dataflow.sources.handle({
|
|
@@ -62,12 +63,12 @@ module.exports = function init(core) {
|
|
|
62
63
|
|
|
63
64
|
sourceContext.parsedCookies = !!Object.keys(req.cookies).length;
|
|
64
65
|
} catch (err) {
|
|
65
|
-
logger.error({
|
|
66
|
+
logger.error({ err, funcKey }, 'unable to handle source');
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
if (sourceContext.parsedSignedCookies) {
|
|
70
|
-
logger.trace({
|
|
71
|
+
logger.trace({ funcKey }, 'signedCookies already tracked');
|
|
71
72
|
} else if (req.signedCookies) {
|
|
72
73
|
try {
|
|
73
74
|
assess.dataflow.sources.handle({
|
|
@@ -83,7 +84,7 @@ module.exports = function init(core) {
|
|
|
83
84
|
|
|
84
85
|
sourceContext.parsedSignedCookies = !!Object.keys(req.signedCookies).length;
|
|
85
86
|
} catch (err) {
|
|
86
|
-
logger.error({
|
|
87
|
+
logger.error({ err, funcKey }, 'unable to handle source');
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -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
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
|
-
const { patchType } = require('
|
|
19
|
+
const { patchType } = require('../../common');
|
|
20
20
|
|
|
21
21
|
module.exports = function init(core) {
|
|
22
22
|
const { depHooks, patcher, logger } = core;
|
|
@@ -30,25 +30,24 @@ module.exports = function init(core) {
|
|
|
30
30
|
patcher.patch(Layer.prototype, 'match', {
|
|
31
31
|
name,
|
|
32
32
|
patchType,
|
|
33
|
-
post(
|
|
34
|
-
const layer = data.obj;
|
|
33
|
+
post({ obj: layer, result, orig, hooked, funcKey }) {
|
|
35
34
|
|
|
36
35
|
// we can exit early if
|
|
37
36
|
// the layer doesn't match the request or
|
|
38
37
|
// the layer doesn't recognize any parameters
|
|
39
|
-
if (!
|
|
38
|
+
if (!result || !layer.keys || layer.keys.length === 0) {
|
|
40
39
|
return;
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
44
43
|
|
|
45
44
|
if (!sourceContext) {
|
|
46
|
-
logger.error({
|
|
45
|
+
logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
47
46
|
return;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
if (sourceContext.parsedParams) {
|
|
51
|
-
logger.trace({
|
|
50
|
+
logger.trace({ funcKey }, 'values already tracked');
|
|
52
51
|
return;
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -58,15 +57,15 @@ module.exports = function init(core) {
|
|
|
58
57
|
name,
|
|
59
58
|
inputType: InputType.PARAMETER_VALUE,
|
|
60
59
|
stacktraceOpts: {
|
|
61
|
-
constructorOpt:
|
|
62
|
-
prependFrames: [
|
|
60
|
+
constructorOpt: hooked,
|
|
61
|
+
prependFrames: [orig]
|
|
63
62
|
},
|
|
64
63
|
data: layer.params,
|
|
65
64
|
sourceContext
|
|
66
65
|
});
|
|
67
66
|
sourceContext.parsedParams = true;
|
|
68
67
|
} catch (err) {
|
|
69
|
-
logger.error({ err,
|
|
68
|
+
logger.error({ err, funcKey }, 'unable to handle source');
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
});
|
|
@@ -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
|
|
|
@@ -31,9 +31,8 @@ module.exports = function (core) {
|
|
|
31
31
|
depHooks.resolve({ name: 'fastify', version: '>=3.0.0' }, (fastify) => patcher.patch(fastify, {
|
|
32
32
|
name: 'fastify.constructor',
|
|
33
33
|
patchType,
|
|
34
|
-
post({ result: server }) {
|
|
34
|
+
post({ result: server, funcKey }) {
|
|
35
35
|
server.addHook('preValidation', function preValidationHandler(request, reply, done) {
|
|
36
|
-
const name = 'fastify.preValidation';
|
|
37
36
|
const bodyType = request?.headers?.['content-type']?.includes('/json')
|
|
38
37
|
? InputType.JSON_VALUE
|
|
39
38
|
: typeof request.body == 'object'
|
|
@@ -42,7 +41,7 @@ module.exports = function (core) {
|
|
|
42
41
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
43
42
|
|
|
44
43
|
if (!sourceContext) {
|
|
45
|
-
logger.error({
|
|
44
|
+
logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
46
45
|
return;
|
|
47
46
|
}
|
|
48
47
|
|
|
@@ -52,7 +51,7 @@ module.exports = function (core) {
|
|
|
52
51
|
{ key: 'body', inputType: bodyType, alreadyTrackedFlag: 'parsedBody' }
|
|
53
52
|
].forEach(({ key, inputType, alreadyTrackedFlag }) => {
|
|
54
53
|
if (sourceContext[alreadyTrackedFlag]) {
|
|
55
|
-
logger.trace({ inputType,
|
|
54
|
+
logger.trace({ inputType, funcKey }, 'values already tracked');
|
|
56
55
|
return;
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -61,14 +60,14 @@ module.exports = function (core) {
|
|
|
61
60
|
context: `req.${key}`,
|
|
62
61
|
data: request[key],
|
|
63
62
|
inputType,
|
|
64
|
-
name,
|
|
63
|
+
name: 'fastify.preValidation',
|
|
65
64
|
stacktraceOpts: {
|
|
66
65
|
constructorOpt: preValidationHandler,
|
|
67
66
|
},
|
|
68
67
|
sourceContext
|
|
69
68
|
});
|
|
70
69
|
} catch (err) {
|
|
71
|
-
logger.error({ err, inputType,
|
|
70
|
+
logger.error({ err, inputType, funcKey }, 'unable to handle Fastify source');
|
|
72
71
|
}
|
|
73
72
|
});
|
|
74
73
|
|
|
@@ -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
|
|
|
@@ -22,7 +22,7 @@ const { toLowerCase, InputType } = require('@contrast/common');
|
|
|
22
22
|
* assess: import('@contrast/assess').Assess,
|
|
23
23
|
* }} core
|
|
24
24
|
*/
|
|
25
|
-
module.exports = function(core) {
|
|
25
|
+
module.exports = function (core) {
|
|
26
26
|
const {
|
|
27
27
|
assess: { dataflow, makeSourceContext },
|
|
28
28
|
instrumentation: { instrument },
|
|
@@ -121,7 +121,7 @@ module.exports = function(core) {
|
|
|
121
121
|
try {
|
|
122
122
|
dataflow.sources.handle(sourceData);
|
|
123
123
|
} catch (err) {
|
|
124
|
-
logger.error({ err, inputType,
|
|
124
|
+
logger.error({ err, inputType, sourceName }, 'unable to handle http source');
|
|
125
125
|
}
|
|
126
126
|
});
|
|
127
127
|
|
|
@@ -130,7 +130,7 @@ module.exports = function(core) {
|
|
|
130
130
|
req.rawHeaders[i + 1] = req.headers[header];
|
|
131
131
|
}
|
|
132
132
|
} catch (err) {
|
|
133
|
-
logger.error({ err }, 'Error during Assess request handling');
|
|
133
|
+
logger.error({ err, funcKey: data.funcKey }, 'Error during Assess request handling');
|
|
134
134
|
}
|
|
135
135
|
|
|
136
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
|
|
|
@@ -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);
|
|
@@ -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
|
});
|