@contrast/assess 1.40.0 → 1.42.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/lib/crypto-analysis/install/crypto.js +4 -5
- package/lib/crypto-analysis/install/crypto.test.js +1 -1
- package/lib/crypto-analysis/install/math.js +2 -4
- package/lib/dataflow/propagation/install/JSON/parse.js +2 -3
- package/lib/dataflow/propagation/install/JSON/stringify.js +3 -4
- package/lib/dataflow/propagation/install/array-prototype-join.js +2 -3
- package/lib/dataflow/propagation/install/buffer.js +3 -4
- package/lib/dataflow/propagation/install/contrast-methods/add.js +2 -3
- package/lib/dataflow/propagation/install/contrast-methods/number.js +2 -3
- package/lib/dataflow/propagation/install/contrast-methods/string.js +2 -3
- package/lib/dataflow/propagation/install/contrast-methods/tag.js +2 -3
- package/lib/dataflow/propagation/install/decode-uri-component.js +2 -3
- package/lib/dataflow/propagation/install/ejs/escape-xml.js +3 -4
- package/lib/dataflow/propagation/install/ejs/template.js +3 -4
- package/lib/dataflow/propagation/install/ejs/template.test.js +1 -1
- package/lib/dataflow/propagation/install/encode-uri.js +2 -3
- package/lib/dataflow/propagation/install/escape-html.js +3 -4
- package/lib/dataflow/propagation/install/escape.js +2 -3
- package/lib/dataflow/propagation/install/fastify-send.js +3 -3
- package/lib/dataflow/propagation/install/fastify-send.test.js +1 -3
- package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +3 -4
- package/lib/dataflow/propagation/install/isnumeric-0.js +1 -1
- package/lib/dataflow/propagation/install/joi/any.js +1 -1
- package/lib/dataflow/propagation/install/joi/any.test.js +1 -1
- package/lib/dataflow/propagation/install/joi/array.test.js +5 -5
- package/lib/dataflow/propagation/install/joi/boolean.js +3 -3
- package/lib/dataflow/propagation/install/joi/boolean.test.js +1 -1
- package/lib/dataflow/propagation/install/joi/expression.js +3 -3
- package/lib/dataflow/propagation/install/joi/expression.test.js +1 -1
- package/lib/dataflow/propagation/install/joi/index.js +3 -3
- package/lib/dataflow/propagation/install/joi/keys.js +3 -3
- package/lib/dataflow/propagation/install/joi/number.js +3 -3
- package/lib/dataflow/propagation/install/joi/number.test.js +1 -1
- package/lib/dataflow/propagation/install/joi/object.js +1 -1
- package/lib/dataflow/propagation/install/joi/object.test.js +1 -1
- package/lib/dataflow/propagation/install/joi/ref.test.js +4 -4
- package/lib/dataflow/propagation/install/joi/string-schema.js +4 -4
- package/lib/dataflow/propagation/install/joi/string-schema.test.js +4 -4
- package/lib/dataflow/propagation/install/joi/values.js +3 -3
- package/lib/dataflow/propagation/install/mongoose/schema-map.js +4 -4
- package/lib/dataflow/propagation/install/mongoose/schema-mixed.js +4 -4
- package/lib/dataflow/propagation/install/mongoose/schema-string.js +4 -4
- package/lib/dataflow/propagation/install/mustache-escape.js +3 -4
- package/lib/dataflow/propagation/install/mustache-escape.test.js +1 -1
- package/lib/dataflow/propagation/install/mysql-connection-escape.js +22 -14
- package/lib/dataflow/propagation/install/mysql-connection-escape.test.js +1 -1
- package/lib/dataflow/propagation/install/parse-int.js +2 -3
- package/lib/dataflow/propagation/install/path/basename.js +3 -4
- package/lib/dataflow/propagation/install/path/dirname.js +3 -4
- package/lib/dataflow/propagation/install/path/extname.js +3 -4
- package/lib/dataflow/propagation/install/path/format.js +3 -4
- package/lib/dataflow/propagation/install/path/index.test.js +1 -1
- package/lib/dataflow/propagation/install/path/join-and-resolve.js +3 -4
- package/lib/dataflow/propagation/install/path/normalize.js +4 -5
- package/lib/dataflow/propagation/install/path/parse.js +3 -4
- package/lib/dataflow/propagation/install/path/relative.js +4 -5
- package/lib/dataflow/propagation/install/path/toNamespacedPath.js +3 -4
- package/lib/dataflow/propagation/install/pug/index.js +3 -4
- package/lib/dataflow/propagation/install/pug-runtime-escape.js +3 -4
- package/lib/dataflow/propagation/install/querystring/escape.js +3 -4
- package/lib/dataflow/propagation/install/querystring/escape.test.js +1 -1
- package/lib/dataflow/propagation/install/querystring/parse.js +3 -4
- package/lib/dataflow/propagation/install/querystring/parse.test.js +1 -1
- package/lib/dataflow/propagation/install/querystring/stringify.js +3 -4
- package/lib/dataflow/propagation/install/querystring/stringify.test.js +1 -1
- package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +2 -3
- package/lib/dataflow/propagation/install/send.js +3 -3
- package/lib/dataflow/propagation/install/sequelize/query-generator.js +3 -3
- package/lib/dataflow/propagation/install/sequelize/query-generator.test.js +2 -1
- package/lib/dataflow/propagation/install/sequelize/sql-string.js +5 -5
- package/lib/dataflow/propagation/install/sql-template-strings.js +3 -3
- package/lib/dataflow/propagation/install/string/concat.js +2 -3
- package/lib/dataflow/propagation/install/string/format-methods.js +2 -3
- package/lib/dataflow/propagation/install/string/html-methods.js +3 -4
- package/lib/dataflow/propagation/install/string/match-all.js +2 -3
- package/lib/dataflow/propagation/install/string/match.js +2 -3
- package/lib/dataflow/propagation/install/string/replace.js +2 -3
- package/lib/dataflow/propagation/install/string/slice.js +2 -3
- package/lib/dataflow/propagation/install/string/split.js +2 -3
- package/lib/dataflow/propagation/install/string/substring.js +2 -3
- package/lib/dataflow/propagation/install/string/trim.js +2 -3
- package/lib/dataflow/propagation/install/unescape.js +2 -3
- package/lib/dataflow/propagation/install/url/domain-parsers.js +3 -4
- package/lib/dataflow/propagation/install/url/parse.js +3 -4
- package/lib/dataflow/propagation/install/url/parse.test.js +2 -2
- package/lib/dataflow/propagation/install/url/searchParams.js +3 -4
- package/lib/dataflow/propagation/install/url/url.js +3 -4
- package/lib/dataflow/propagation/install/util-format.js +3 -4
- package/lib/dataflow/propagation/install/validator/hooks.js +9 -9
- package/lib/dataflow/sinks/install/child-process.js +5 -6
- package/lib/dataflow/sinks/install/eval.js +2 -3
- package/lib/dataflow/sinks/install/express/reflected-xss.js +3 -4
- package/lib/dataflow/sinks/install/express/unvalidated-redirect.js +3 -4
- package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js +3 -4
- package/lib/dataflow/sinks/install/fs.js +4 -5
- package/lib/dataflow/sinks/install/fs.test.js +2 -2
- package/lib/dataflow/sinks/install/function.js +2 -3
- package/lib/dataflow/sinks/install/hapi/unvalidated-redirect.js +3 -4
- package/lib/dataflow/sinks/install/http/request.js +3 -4
- package/lib/dataflow/sinks/install/http/request.test.js +2 -2
- package/lib/dataflow/sinks/install/http/server-response.js +5 -6
- package/lib/dataflow/sinks/install/http/server-response.test.js +3 -3
- package/lib/dataflow/sinks/install/koa/unvalidated-redirect.js +3 -4
- package/lib/dataflow/sinks/install/libxmljs.js +4 -5
- package/lib/dataflow/sinks/install/libxmljs.test.js +2 -2
- package/lib/dataflow/sinks/install/marsdb.js +3 -4
- package/lib/dataflow/sinks/install/marsdb.test.js +3 -3
- package/lib/dataflow/sinks/install/mongodb.js +3 -4
- package/lib/dataflow/sinks/install/mongodb.test.js +2 -6
- package/lib/dataflow/sinks/install/mssql.js +4 -5
- package/lib/dataflow/sinks/install/mssql.test.js +2 -2
- package/lib/dataflow/sinks/install/mysql.js +4 -5
- package/lib/dataflow/sinks/install/mysql.test.js +2 -11
- package/lib/dataflow/sinks/install/node-serialize.js +3 -4
- package/lib/dataflow/sinks/install/node-serialize.test.js +1 -3
- package/lib/dataflow/sinks/install/postgres.js +5 -6
- package/lib/dataflow/sinks/install/postgres.test.js +3 -9
- package/lib/dataflow/sinks/install/restify.js +3 -4
- package/lib/dataflow/sinks/install/restify.test.js +3 -5
- package/lib/dataflow/sinks/install/sequelize.js +3 -4
- package/lib/dataflow/sinks/install/sqlite3.js +3 -4
- package/lib/dataflow/sinks/install/vm.js +3 -4
- package/lib/dataflow/sources/install/body-parser1.js +2 -4
- package/lib/dataflow/sources/install/body-parser1.test.js +4 -8
- package/lib/dataflow/sources/install/busboy.js +3 -4
- package/lib/dataflow/sources/install/busboy.test.js +2 -2
- package/lib/dataflow/sources/install/cookie-parser1.js +2 -4
- package/lib/dataflow/sources/install/cookie-parser1.test.js +2 -4
- package/lib/dataflow/sources/install/express/params.js +56 -38
- package/lib/dataflow/sources/install/express/params.test.js +80 -73
- package/lib/dataflow/sources/install/express/parsedUrl.js +45 -29
- package/lib/dataflow/sources/install/express/parsedUrl.test.js +71 -29
- package/lib/dataflow/sources/install/fastify/fastify.js +2 -3
- package/lib/dataflow/sources/install/fastify/fastify.test.js +3 -6
- package/lib/dataflow/sources/install/formidable1.js +2 -3
- package/lib/dataflow/sources/install/hapi/hapi.js +1 -2
- package/lib/dataflow/sources/install/http.js +2 -3
- package/lib/dataflow/sources/install/http.test.js +2 -2
- package/lib/dataflow/sources/install/koa/koa-bodyparsers.js +3 -5
- package/lib/dataflow/sources/install/koa/koa-multer.js +3 -4
- package/lib/dataflow/sources/install/koa/koa-multer.test.js +1 -1
- package/lib/dataflow/sources/install/koa/koa-routers.js +3 -4
- package/lib/dataflow/sources/install/koa/koa2.js +2 -4
- package/lib/dataflow/sources/install/multer1.js +2 -3
- package/lib/dataflow/sources/install/multer1.test.js +1 -3
- package/lib/dataflow/sources/install/qs6.js +2 -4
- package/lib/dataflow/sources/install/querystring.js +2 -3
- package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.js +2 -3
- package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.test.js +1 -1
- package/lib/dataflow/sources/install/restify/jsonBodyParser.js +2 -3
- package/lib/dataflow/sources/install/restify/jsonBodyParser.test.js +1 -1
- package/lib/dataflow/sources/install/restify/router.js +2 -4
- package/lib/dataflow/sources/install/restify/router.test.js +4 -6
- package/lib/get-source-context.js +77 -37
- package/lib/get-source-context.test.js +106 -53
- package/lib/index.d.ts +3 -9
- package/lib/response-scanning/install/http.js +3 -3
- package/lib/response-scanning/install/http.test.js +2 -2
- package/lib/session-configuration/install/express-session.js +1 -1
- package/lib/session-configuration/install/express-session.test.js +1 -3
- package/lib/session-configuration/install/fastify-cookie.js +1 -1
- package/lib/session-configuration/install/fastify-cookie.test.js +1 -3
- package/lib/session-configuration/install/koa.js +1 -1
- package/lib/session-configuration/install/koa.test.js +1 -1
- package/package.json +11 -11
- package/lib/constants.js +0 -26
- package/lib/dataflow/sinks/install/fs-original.js +0 -170
|
@@ -28,15 +28,9 @@ describe('assess dataflow sinks postgres', function () {
|
|
|
28
28
|
reportFindings = sinon.stub(core.assess.dataflow.sinks, 'reportFindings');
|
|
29
29
|
reportSafePositive = sinon.stub(core.assess.dataflow.sinks, 'reportSafePositive');
|
|
30
30
|
|
|
31
|
-
core.depHooks.resolve
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
core.depHooks.resolve
|
|
36
|
-
.withArgs({ name: 'pg', file: 'lib/native/client.js' })
|
|
37
|
-
.yields(NativeClient);
|
|
38
|
-
|
|
39
|
-
core.depHooks.resolve.withArgs({ name: 'pg-pool' }).yields(Pool);
|
|
31
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: 'pg', file: 'lib/client.js' })).yields(Client);
|
|
32
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: 'pg', file: 'lib/native/client.js' })).yields(NativeClient);
|
|
33
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: 'pg-pool' })).yields(Pool);
|
|
40
34
|
|
|
41
35
|
require('./postgres')(core).install();
|
|
42
36
|
});
|
|
@@ -28,7 +28,6 @@ const {
|
|
|
28
28
|
isString,
|
|
29
29
|
primordials: { ArrayPrototypeJoin },
|
|
30
30
|
} = require('@contrast/common');
|
|
31
|
-
const { InstrumentationType: { RULE } } = require('../../../constants');
|
|
32
31
|
const { createAppendTags } = require('../../tag-utils');
|
|
33
32
|
const { patchType } = require('../common');
|
|
34
33
|
|
|
@@ -45,7 +44,7 @@ module.exports = function(core) {
|
|
|
45
44
|
depHooks,
|
|
46
45
|
patcher,
|
|
47
46
|
assess: {
|
|
48
|
-
|
|
47
|
+
getSinkContext,
|
|
49
48
|
eventFactory: { createSinkEvent },
|
|
50
49
|
dataflow: {
|
|
51
50
|
tracker,
|
|
@@ -114,7 +113,7 @@ module.exports = function(core) {
|
|
|
114
113
|
install() {
|
|
115
114
|
// restify adds functionality to the built-in response via this patch function.
|
|
116
115
|
// once it returns the request, it'll have been decorated with redirect() method.
|
|
117
|
-
depHooks.resolve({ name: 'restify', file: 'lib/response.js' }, (responsePatch) => patcher.patch(responsePatch, {
|
|
116
|
+
depHooks.resolve({ name: 'restify', version: '<12', file: 'lib/response.js' }, (responsePatch) => patcher.patch(responsePatch, {
|
|
118
117
|
name: 'restify.response.patch',
|
|
119
118
|
patchType,
|
|
120
119
|
post(data) {
|
|
@@ -122,7 +121,7 @@ module.exports = function(core) {
|
|
|
122
121
|
patchType,
|
|
123
122
|
name: 'restify.Response.redirect',
|
|
124
123
|
pre(data) {
|
|
125
|
-
if (!
|
|
124
|
+
if (!getSinkContext(ruleId)) return;
|
|
126
125
|
|
|
127
126
|
let vulnArgIdx;
|
|
128
127
|
let vulnArgIsString = true;
|
|
@@ -33,11 +33,9 @@ describe('assess dataflow restify sinks', function () {
|
|
|
33
33
|
return new Response();
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
core.depHooks.resolve
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
patchMock = cb(patch);
|
|
40
|
-
});
|
|
36
|
+
core.depHooks.resolve.callsFake((desc, cb) => {
|
|
37
|
+
patchMock = cb(patch);
|
|
38
|
+
});
|
|
41
39
|
|
|
42
40
|
require('./restify')(core).install();
|
|
43
41
|
});
|
|
@@ -25,7 +25,6 @@ const {
|
|
|
25
25
|
CUSTOM_ENCODED,
|
|
26
26
|
},
|
|
27
27
|
} = require('@contrast/common');
|
|
28
|
-
const { InstrumentationType: { RULE } } = require('../../../constants');
|
|
29
28
|
const { patchType, filterSafeTags } = require('../common');
|
|
30
29
|
|
|
31
30
|
/**
|
|
@@ -42,7 +41,7 @@ module.exports = function (core) {
|
|
|
42
41
|
config,
|
|
43
42
|
assess: {
|
|
44
43
|
inspect, // TODO NODE-3455: remove
|
|
45
|
-
|
|
44
|
+
getSinkContext,
|
|
46
45
|
eventFactory: { createSinkEvent },
|
|
47
46
|
dataflow: {
|
|
48
47
|
tracker,
|
|
@@ -63,12 +62,12 @@ module.exports = function (core) {
|
|
|
63
62
|
const sequelize = (core.assess.dataflow.sinks.sequelize = {});
|
|
64
63
|
|
|
65
64
|
sequelize.install = function () {
|
|
66
|
-
depHooks.resolve({ name: 'sequelize' }, (sequelize) => {
|
|
65
|
+
depHooks.resolve({ name: 'sequelize', version: '<7' }, (sequelize) => {
|
|
67
66
|
patcher.patch(sequelize.prototype, 'query', {
|
|
68
67
|
name: 'sequelize.prototype.query',
|
|
69
68
|
patchType,
|
|
70
69
|
around(next, data) {
|
|
71
|
-
if (!
|
|
70
|
+
if (!getSinkContext(ruleId) || !data.args[0]) return next();
|
|
72
71
|
|
|
73
72
|
const { args, hooked, orig } = data;
|
|
74
73
|
const query = typeof args[0] === 'string' ? args[0] : args[0].query;
|
|
@@ -27,7 +27,6 @@ const {
|
|
|
27
27
|
Rule: { SQL_INJECTION: ruleId },
|
|
28
28
|
isString
|
|
29
29
|
} = require('@contrast/common');
|
|
30
|
-
const { InstrumentationType: { RULE } } = require('../../../constants');
|
|
31
30
|
|
|
32
31
|
const safeTags = [
|
|
33
32
|
`excluded:${ruleId}`,
|
|
@@ -49,7 +48,7 @@ module.exports = function(core) {
|
|
|
49
48
|
depHooks,
|
|
50
49
|
patcher,
|
|
51
50
|
assess: {
|
|
52
|
-
|
|
51
|
+
getSinkContext,
|
|
53
52
|
eventFactory: { createSinkEvent },
|
|
54
53
|
dataflow: {
|
|
55
54
|
tracker,
|
|
@@ -60,7 +59,7 @@ module.exports = function(core) {
|
|
|
60
59
|
|
|
61
60
|
const pre = (name, method) => (data) => {
|
|
62
61
|
if (
|
|
63
|
-
!
|
|
62
|
+
!getSinkContext(ruleId) ||
|
|
64
63
|
!data.args[0] ||
|
|
65
64
|
!isString(data.args[0]) ||
|
|
66
65
|
isLocked(ruleId)
|
|
@@ -105,7 +104,7 @@ module.exports = function(core) {
|
|
|
105
104
|
|
|
106
105
|
core.assess.dataflow.sinks.sqlite3 = {
|
|
107
106
|
install() {
|
|
108
|
-
depHooks.resolve({ name: 'sqlite3' }, sqlite3 => {
|
|
107
|
+
depHooks.resolve({ name: 'sqlite3', version: '<6' }, sqlite3 => {
|
|
109
108
|
['all', 'run', 'get', 'each', 'exec', 'prepare'].forEach((method) => {
|
|
110
109
|
const name = `sqlite3.Database.prototype.${method}`;
|
|
111
110
|
patcher.patch(sqlite3.Database.prototype, method, {
|
|
@@ -33,7 +33,6 @@ const {
|
|
|
33
33
|
},
|
|
34
34
|
traverseValues,
|
|
35
35
|
} = require('@contrast/common');
|
|
36
|
-
const { InstrumentationType: { RULE } } = require('../../../constants');
|
|
37
36
|
const { createAdjustedQueryTags } = require('../../tag-utils');
|
|
38
37
|
|
|
39
38
|
const safeTags = [
|
|
@@ -58,7 +57,7 @@ module.exports = function (core) {
|
|
|
58
57
|
patcher,
|
|
59
58
|
assess: {
|
|
60
59
|
inspect, // TODO NODE-3455: remove
|
|
61
|
-
|
|
60
|
+
getSinkContext,
|
|
62
61
|
eventFactory: { createSinkEvent },
|
|
63
62
|
dataflow: {
|
|
64
63
|
tracker,
|
|
@@ -144,7 +143,7 @@ module.exports = function (core) {
|
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
function around(next, { args: origArgs, hooked, orig, name }) {
|
|
147
|
-
if (!
|
|
146
|
+
if (!getSinkContext(ruleId) || isLocked(ruleId)) return next();
|
|
148
147
|
|
|
149
148
|
const methodPath = StringPrototypeSplit.call(name, '.');
|
|
150
149
|
const method = methodPath[methodPath.length - 1];
|
|
@@ -250,7 +249,7 @@ module.exports = function (core) {
|
|
|
250
249
|
|
|
251
250
|
core.assess.dataflow.sinks.vm = {
|
|
252
251
|
install() {
|
|
253
|
-
depHooks.resolve({ name: 'vm' }, (vm) => {
|
|
252
|
+
depHooks.resolve({ name: 'vm', version: '*' }, (vm) => {
|
|
254
253
|
[
|
|
255
254
|
'Script',
|
|
256
255
|
'createScript',
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
|
-
const { InstrumentationType: { SOURCE } } = require('../../../constants');
|
|
20
19
|
const { patchType } = require('../common');
|
|
21
20
|
|
|
22
21
|
const METHODS = ['json', 'raw', 'text', 'urlencoded'];
|
|
@@ -39,10 +38,9 @@ module.exports = function init(core) {
|
|
|
39
38
|
const preHook = (data) => {
|
|
40
39
|
const [req, , next] = data.args;
|
|
41
40
|
data.args[2] = scopes.wrap(function contrastNext(...args) {
|
|
42
|
-
const sourceContext = getSourceContext(
|
|
41
|
+
const sourceContext = getSourceContext();
|
|
43
42
|
|
|
44
43
|
if (!sourceContext) {
|
|
45
|
-
logger.error({ funcKey: data.funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
46
44
|
return next(...args);
|
|
47
45
|
}
|
|
48
46
|
|
|
@@ -99,7 +97,7 @@ module.exports = function init(core) {
|
|
|
99
97
|
core.assess.dataflow.sources.bodyParser1Instrumentation = {
|
|
100
98
|
install() {
|
|
101
99
|
depHooks.resolve(
|
|
102
|
-
{ name: 'body-parser', version: '>=1
|
|
100
|
+
{ name: 'body-parser', version: '>=1 <2' },
|
|
103
101
|
/** @param {import('body-parser').BodyParser} bodyParser */
|
|
104
102
|
(bodyParser) => {
|
|
105
103
|
bodyParser = patcher.patch(bodyParser, {
|
|
@@ -112,10 +112,8 @@ describe('assess dataflow sources body-parser v1', function () {
|
|
|
112
112
|
middleware(req, res, next);
|
|
113
113
|
|
|
114
114
|
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
115
|
-
expect(core.logger.
|
|
116
|
-
|
|
117
|
-
'unable to handle source. Missing `sourceContext`'
|
|
118
|
-
);
|
|
115
|
+
expect(core.logger.trace.callCount).greaterThan(0);
|
|
116
|
+
expect(core.logger.trace.lastCall.args[0]).includes('Assess intentionally disabled');
|
|
119
117
|
}, { assess: { policy: null } });
|
|
120
118
|
});
|
|
121
119
|
|
|
@@ -210,10 +208,8 @@ describe('assess dataflow sources body-parser v1', function () {
|
|
|
210
208
|
middleware(req, res, next);
|
|
211
209
|
|
|
212
210
|
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
213
|
-
expect(core.logger.
|
|
214
|
-
|
|
215
|
-
'unable to handle source. Missing `sourceContext`',
|
|
216
|
-
);
|
|
211
|
+
expect(core.logger.trace.callCount).greaterThan(0);
|
|
212
|
+
expect(core.logger.trace.lastCall.args[0]).includes('Assess intentionally disabled');
|
|
217
213
|
}, { assess: { policy: null } });
|
|
218
214
|
});
|
|
219
215
|
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
|
-
const { InstrumentationType: { SOURCE } } = require('../../../constants');
|
|
20
19
|
const { patchType } = require('../common');
|
|
21
20
|
|
|
22
21
|
const inputType = InputType.MULTIPART_VALUE;
|
|
@@ -38,7 +37,7 @@ module.exports = (core) => {
|
|
|
38
37
|
function createPreHook(finalEventName) {
|
|
39
38
|
return function (data) {
|
|
40
39
|
const { orig, hooked, funcKey } = data;
|
|
41
|
-
const sourceContext = getSourceContext(
|
|
40
|
+
const sourceContext = getSourceContext();
|
|
42
41
|
|
|
43
42
|
if (!sourceContext) {
|
|
44
43
|
return;
|
|
@@ -84,7 +83,7 @@ module.exports = (core) => {
|
|
|
84
83
|
|
|
85
84
|
// Patch `busboy`
|
|
86
85
|
function install() {
|
|
87
|
-
depHooks.resolve({ name, version: '<1
|
|
86
|
+
depHooks.resolve({ name, version: '<1' }, (busboy) => {
|
|
88
87
|
patcher.patch(busboy.prototype, 'emit', {
|
|
89
88
|
name: 'busboy.prototype.emit',
|
|
90
89
|
patchType,
|
|
@@ -93,7 +92,7 @@ module.exports = (core) => {
|
|
|
93
92
|
});
|
|
94
93
|
|
|
95
94
|
|
|
96
|
-
depHooks.resolve({ name, version: '
|
|
95
|
+
depHooks.resolve({ name, version: '1' }, (busboy) =>
|
|
97
96
|
patcher.patch(busboy, {
|
|
98
97
|
name,
|
|
99
98
|
patchType,
|
|
@@ -27,8 +27,8 @@ describe('assess dataflow sources busboy', function () {
|
|
|
27
27
|
sinon.spy(sources, 'handle');
|
|
28
28
|
|
|
29
29
|
busboyInstr(core).install();
|
|
30
|
-
core.depHooks.resolve.withArgs({ name: 'busboy', version: '<1
|
|
31
|
-
core.depHooks.resolve.withArgs({ name: 'busboy', version: '
|
|
30
|
+
core.depHooks.resolve.withArgs({ name: 'busboy', version: '<1' }).yield(mockBusboy0);
|
|
31
|
+
core.depHooks.resolve.withArgs({ name: 'busboy', version: '1' }).yield(mockBusboy1);
|
|
32
32
|
const patchedBusboy1 = core.patcher.patch.getCall(1).returnValue;
|
|
33
33
|
|
|
34
34
|
emitMethodVersions = {
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
|
-
const { InstrumentationType: { SOURCE } } = require('../../../constants');
|
|
20
19
|
const { patchType } = require('../common');
|
|
21
20
|
|
|
22
21
|
module.exports = function init(core) {
|
|
@@ -25,7 +24,7 @@ module.exports = function init(core) {
|
|
|
25
24
|
assess.dataflow.sources.cookieParser1Instrumentation = {
|
|
26
25
|
install() {
|
|
27
26
|
depHooks.resolve(
|
|
28
|
-
{ name: 'cookie-parser', version: '>=1
|
|
27
|
+
{ name: 'cookie-parser', version: '>=1 <2' },
|
|
29
28
|
/** @param {import('cookie-parser')} cookieParser */
|
|
30
29
|
(cookieParser) =>
|
|
31
30
|
patcher.patch(cookieParser, {
|
|
@@ -40,10 +39,9 @@ module.exports = function init(core) {
|
|
|
40
39
|
const { funcKey } = data;
|
|
41
40
|
const [req, , next] = data.args;
|
|
42
41
|
data.args[2] = function contrastNext(...args) {
|
|
43
|
-
const sourceContext = assess.getSourceContext(
|
|
42
|
+
const sourceContext = assess.getSourceContext();
|
|
44
43
|
|
|
45
44
|
if (!sourceContext) {
|
|
46
|
-
logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
47
45
|
return next(...args);
|
|
48
46
|
}
|
|
49
47
|
|
|
@@ -74,10 +74,8 @@ describe('assess dataflow sources cookie-parser v1', function () {
|
|
|
74
74
|
middleware(req, res, next);
|
|
75
75
|
|
|
76
76
|
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
77
|
-
expect(core.logger.
|
|
78
|
-
|
|
79
|
-
'unable to handle source. Missing `sourceContext`',
|
|
80
|
-
);
|
|
77
|
+
expect(core.logger.trace.callCount).greaterThan(0);
|
|
78
|
+
expect(core.logger.trace.lastCall.args[0]).includes('Assess intentionally disabled');
|
|
81
79
|
}, { assess: { policy: null } });
|
|
82
80
|
});
|
|
83
81
|
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
|
-
const { InstrumentationType: { SOURCE } } = require('../../../../constants');
|
|
20
19
|
const { patchType } = require('../../common');
|
|
21
20
|
|
|
22
21
|
module.exports = function init(core) {
|
|
@@ -24,55 +23,74 @@ module.exports = function init(core) {
|
|
|
24
23
|
logger,
|
|
25
24
|
patcher,
|
|
26
25
|
depHooks,
|
|
27
|
-
assess: {
|
|
26
|
+
assess: {
|
|
27
|
+
getSourceContext,
|
|
28
|
+
dataflow: { sources }
|
|
29
|
+
},
|
|
28
30
|
} = core;
|
|
29
31
|
|
|
32
|
+
function postHook(name) {
|
|
33
|
+
return function({ obj: layer, result, orig, hooked, funcKey }) {
|
|
34
|
+
// we can exit early if
|
|
35
|
+
// the layer doesn't match the request or
|
|
36
|
+
// the layer doesn't recognize any parameters
|
|
37
|
+
if (
|
|
38
|
+
!result ||
|
|
39
|
+
!layer.keys ||
|
|
40
|
+
layer.keys.length === 0
|
|
41
|
+
) return;
|
|
42
|
+
|
|
43
|
+
const sourceContext = getSourceContext();
|
|
44
|
+
if (!sourceContext) return;
|
|
45
|
+
|
|
46
|
+
if (sourceContext.parsedParams) {
|
|
47
|
+
logger.trace({ funcKey }, 'values already tracked');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
sources.handle({
|
|
53
|
+
context: 'req.params',
|
|
54
|
+
name,
|
|
55
|
+
inputType: InputType.PARAMETER_VALUE,
|
|
56
|
+
stacktraceOpts: {
|
|
57
|
+
constructorOpt: hooked,
|
|
58
|
+
prependFrames: [orig]
|
|
59
|
+
},
|
|
60
|
+
data: layer.params,
|
|
61
|
+
sourceContext
|
|
62
|
+
});
|
|
63
|
+
sourceContext.parsedParams = true;
|
|
64
|
+
} catch (err) {
|
|
65
|
+
logger.error({ err, funcKey }, 'unable to handle source');
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
30
70
|
core.assess.dataflow.sources.expressInstrumentation.params = {
|
|
31
71
|
install() {
|
|
32
72
|
const name = 'Layer.prototype.match';
|
|
33
73
|
depHooks.resolve(
|
|
34
|
-
{ name: 'express', version: '>=4
|
|
74
|
+
{ name: 'express', version: '>=4 <5', file: 'lib/router/layer.js' },
|
|
35
75
|
(Layer) => {
|
|
36
76
|
patcher.patch(Layer.prototype, 'match', {
|
|
37
77
|
name,
|
|
38
78
|
patchType,
|
|
39
|
-
post
|
|
40
|
-
// we can exit early if
|
|
41
|
-
// the layer doesn't match the request or
|
|
42
|
-
// the layer doesn't recognize any parameters
|
|
43
|
-
if (
|
|
44
|
-
!result ||
|
|
45
|
-
!layer.keys ||
|
|
46
|
-
layer.keys.length === 0
|
|
47
|
-
) return;
|
|
48
|
-
|
|
49
|
-
const sourceContext = getSourceContext(SOURCE);
|
|
50
|
-
if (!sourceContext) return;
|
|
51
|
-
|
|
52
|
-
if (sourceContext.parsedParams) {
|
|
53
|
-
logger.trace({ funcKey }, 'values already tracked');
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
core.assess.dataflow.sources.handle({
|
|
59
|
-
context: 'req.params',
|
|
60
|
-
name,
|
|
61
|
-
inputType: InputType.PARAMETER_VALUE,
|
|
62
|
-
stacktraceOpts: {
|
|
63
|
-
constructorOpt: hooked,
|
|
64
|
-
prependFrames: [orig]
|
|
65
|
-
},
|
|
66
|
-
data: layer.params,
|
|
67
|
-
sourceContext
|
|
68
|
-
});
|
|
69
|
-
sourceContext.parsedParams = true;
|
|
70
|
-
} catch (err) {
|
|
71
|
-
logger.error({ err, funcKey }, 'unable to handle source');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
79
|
+
post: postHook(name)
|
|
74
80
|
});
|
|
81
|
+
return Layer;
|
|
82
|
+
}
|
|
83
|
+
);
|
|
75
84
|
|
|
85
|
+
// Used by Express 5
|
|
86
|
+
depHooks.resolve(
|
|
87
|
+
{ name: 'router', version: '>=2 <3', file: 'lib/layer.js' },
|
|
88
|
+
(Layer) => {
|
|
89
|
+
patcher.patch(Layer.prototype, 'match', {
|
|
90
|
+
name,
|
|
91
|
+
patchType,
|
|
92
|
+
post: postHook(name)
|
|
93
|
+
});
|
|
76
94
|
return Layer;
|
|
77
95
|
}
|
|
78
96
|
);
|
|
@@ -8,96 +8,103 @@ const { InputType } = require('@contrast/common');
|
|
|
8
8
|
describe('assess dataflow sources express params', function () {
|
|
9
9
|
let core, simulateRequestScope, Layer, layer;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
[
|
|
12
|
+
{ name: 'express', version: '>=4 <5', file: 'lib/router/layer.js' },
|
|
13
|
+
{ name: 'router', version: '>=2 <3', file: 'lib/layer.js' }
|
|
14
|
+
].forEach((args) => {
|
|
15
|
+
describe(`Express${args.name === 'express' ? '4' : '5'}`, function() {
|
|
16
|
+
beforeEach(function () {
|
|
17
|
+
({ core, simulateRequestScope } = initAssessFixture());
|
|
18
|
+
|
|
19
|
+
sinon.stub(core.assess.dataflow.sources, 'handle');
|
|
20
|
+
|
|
21
|
+
const LayerMock = sinon.stub();
|
|
22
|
+
LayerMock.prototype.match = sinon.stub().returns(true);
|
|
23
|
+
|
|
24
|
+
require('./params')(core).install();
|
|
25
|
+
[Layer] = core.depHooks.resolve.withArgs(args).yield(LayerMock);
|
|
26
|
+
layer = { keys: ['foo'], params: { foo: 'bar' } };
|
|
27
|
+
});
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
it('calls `.handle` when `match` adds params (and keys) to the Layer instance', function () {
|
|
30
|
+
simulateRequestScope(() => {
|
|
31
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
32
|
+
|
|
33
|
+
expect(core.assess.dataflow.sources.handle).to.have.been.calledWith({
|
|
34
|
+
context: 'req.params',
|
|
35
|
+
name: 'Layer.prototype.match',
|
|
36
|
+
inputType: InputType.PARAMETER_VALUE,
|
|
37
|
+
stacktraceOpts: {
|
|
38
|
+
constructorOpt: sinon.match.func,
|
|
39
|
+
prependFrames: sinon.match.array,
|
|
40
|
+
},
|
|
41
|
+
data: layer.params,
|
|
42
|
+
sourceContext: core.scopes.sources.getStore().assess
|
|
43
|
+
});
|
|
44
|
+
});
|
|
38
45
|
});
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
it('does not call `.handle` when `match` returns false', function () {
|
|
48
|
+
Layer.prototype.match.returns(false);
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
simulateRequestScope(() => {
|
|
51
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
54
|
+
});
|
|
55
|
+
});
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
it('does not call `.handle` when the layer is missing the expected properties', function () {
|
|
58
|
+
simulateRequestScope(() => {
|
|
59
|
+
Reflect.apply(Layer.prototype.match, {}, ['/bar']);
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
62
|
+
});
|
|
63
|
+
});
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
it('does not call `.handle` when `match` adds no params or keys', function () {
|
|
66
|
+
simulateRequestScope(() => {
|
|
67
|
+
Reflect.apply(Layer.prototype.match, { keys: [], params: {} }, ['/bar']);
|
|
63
68
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
70
|
+
});
|
|
71
|
+
});
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
it('does not handle when there is no assess policy in request context', function () {
|
|
74
|
+
simulateRequestScope(() => {
|
|
75
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
71
76
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
78
|
+
}, { assess: { policy: null } });
|
|
79
|
+
});
|
|
75
80
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
it('does not call `.handle` when the values are already tracked', function () {
|
|
82
|
+
simulateRequestScope(() => {
|
|
83
|
+
core.scopes.sources.getStore().assess.parsedParams = true;
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
81
86
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
expect(core.assess.dataflow.sources.handle).not.to.have.been.called;
|
|
88
|
+
expect(core.logger.trace).to.have.been.calledWith(
|
|
89
|
+
{ funcKey: 'assess-dataflow-source:Layer.prototype.match' },
|
|
90
|
+
'values already tracked'
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
it('handles a case with an error in the `.handle` method', function () {
|
|
96
|
+
const err = new Error('test');
|
|
97
|
+
core.assess.dataflow.sources.handle.throws(err);
|
|
93
98
|
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
simulateRequestScope(() => {
|
|
100
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
expect(core.logger.error).to.have.been.calledWith(
|
|
103
|
+
{ err, funcKey: 'assess-dataflow-source:Layer.prototype.match' },
|
|
104
|
+
'unable to handle source'
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
101
108
|
});
|
|
102
109
|
});
|
|
103
110
|
});
|