@contrast/assess 1.34.0 → 1.36.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 +1 -1
- package/lib/dataflow/propagation/install/JSON/parse-fn.js +1 -1
- package/lib/dataflow/propagation/install/JSON/parse.js +3 -2
- package/lib/dataflow/propagation/install/JSON/parse.test.js +2 -2
- package/lib/dataflow/propagation/install/JSON/stringify.js +11 -10
- package/lib/dataflow/propagation/install/JSON/stringify.test.js +3 -3
- package/lib/dataflow/propagation/install/array-prototype-join.js +4 -3
- package/lib/dataflow/propagation/install/array-prototype-join.test.js +3 -3
- package/lib/dataflow/propagation/install/buffer.js +2 -3
- package/lib/dataflow/propagation/install/contrast-methods/tag.test.js +2 -2
- package/lib/dataflow/propagation/install/decode-uri-component.js +5 -8
- package/lib/dataflow/propagation/install/decode-uri-component.test.js +1 -1
- package/lib/dataflow/propagation/install/ejs/escape-xml.js +6 -9
- package/lib/dataflow/propagation/install/ejs/escape-xml.test.js +2 -2
- package/lib/dataflow/propagation/install/ejs/template.js +2 -2
- package/lib/dataflow/propagation/install/encode-uri.js +4 -6
- package/lib/dataflow/propagation/install/encode-uri.test.js +2 -2
- package/lib/dataflow/propagation/install/escape-html.js +5 -8
- package/lib/dataflow/propagation/install/escape-html.test.js +3 -3
- package/lib/dataflow/propagation/install/escape.js +5 -8
- package/lib/dataflow/propagation/install/escape.test.js +2 -2
- package/lib/dataflow/propagation/install/fastify-send.js +3 -5
- package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +6 -9
- package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.test.js +1 -1
- package/lib/dataflow/propagation/install/joi/boolean.js +50 -52
- package/lib/dataflow/propagation/install/joi/expression.js +3 -10
- package/lib/dataflow/propagation/install/joi/index.js +98 -101
- package/lib/dataflow/propagation/install/joi/keys.js +10 -5
- package/lib/dataflow/propagation/install/joi/number.js +50 -52
- package/lib/dataflow/propagation/install/joi/string-schema.js +9 -14
- package/lib/dataflow/propagation/install/joi/utils.js +7 -4
- package/lib/dataflow/propagation/install/joi/values.js +5 -7
- package/lib/dataflow/propagation/install/mongoose/schema-map.js +5 -4
- package/lib/dataflow/propagation/install/mongoose/schema-map.test.js +4 -4
- package/lib/dataflow/propagation/install/mongoose/schema-mixed.js +5 -4
- package/lib/dataflow/propagation/install/mongoose/schema-mixed.test.js +4 -5
- package/lib/dataflow/propagation/install/mongoose/schema-string.js +3 -4
- package/lib/dataflow/propagation/install/mustache-escape.js +5 -8
- package/lib/dataflow/propagation/install/mustache-escape.test.js +2 -2
- package/lib/dataflow/propagation/install/mysql-connection-escape.js +5 -8
- package/lib/dataflow/propagation/install/mysql-connection-escape.test.js +2 -2
- package/lib/dataflow/propagation/install/parse-int.js +3 -3
- package/lib/dataflow/propagation/install/path/basename.js +7 -12
- package/lib/dataflow/propagation/install/path/basename.test.js +2 -2
- package/lib/dataflow/propagation/install/path/common.js +2 -2
- package/lib/dataflow/propagation/install/path/dirname.js +5 -10
- package/lib/dataflow/propagation/install/path/dirname.test.js +2 -2
- package/lib/dataflow/propagation/install/path/extname.js +6 -11
- package/lib/dataflow/propagation/install/path/extname.test.js +2 -2
- package/lib/dataflow/propagation/install/path/format.js +7 -13
- package/lib/dataflow/propagation/install/path/format.test.js +2 -2
- package/lib/dataflow/propagation/install/path/join-and-resolve.js +7 -12
- package/lib/dataflow/propagation/install/path/join-and-resolve.test.js +2 -2
- package/lib/dataflow/propagation/install/path/normalize.js +4 -11
- package/lib/dataflow/propagation/install/path/normalize.test.js +2 -2
- package/lib/dataflow/propagation/install/path/parse.js +3 -8
- package/lib/dataflow/propagation/install/path/parse.test.js +2 -2
- package/lib/dataflow/propagation/install/path/relative.js +5 -11
- package/lib/dataflow/propagation/install/path/relative.test.js +2 -2
- package/lib/dataflow/propagation/install/path/toNamespacedPath.js +5 -11
- package/lib/dataflow/propagation/install/path/toNamespacedPath.test.js +2 -2
- package/lib/dataflow/propagation/install/pug/index.js +8 -3
- package/lib/dataflow/propagation/install/pug-runtime-escape.js +5 -8
- package/lib/dataflow/propagation/install/pug-runtime-escape.test.js +1 -1
- package/lib/dataflow/propagation/install/querystring/escape.js +3 -3
- package/lib/dataflow/propagation/install/querystring/parse.js +7 -11
- package/lib/dataflow/propagation/install/querystring/stringify.js +3 -3
- package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +4 -3
- package/lib/dataflow/propagation/install/reg-exp-prototype-exec.test.js +5 -3
- package/lib/dataflow/propagation/install/send.js +5 -10
- package/lib/dataflow/propagation/install/sequelize/query-generator.js +3 -4
- package/lib/dataflow/propagation/install/sequelize/sql-string.js +8 -12
- package/lib/dataflow/propagation/install/sequelize/sql-string.test.js +2 -13
- package/lib/dataflow/propagation/install/sql-template-strings.js +3 -5
- package/lib/dataflow/propagation/install/sql-template-strings.test.js +2 -2
- package/lib/dataflow/propagation/install/string/concat.js +2 -1
- package/lib/dataflow/propagation/install/string/concat.test.js +15 -2
- package/lib/dataflow/propagation/install/string/format-methods.js +4 -2
- package/lib/dataflow/propagation/install/string/format-methods.test.js +15 -2
- package/lib/dataflow/propagation/install/string/html-methods.js +1 -1
- package/lib/dataflow/propagation/install/string/html-methods.test.js +15 -2
- package/lib/dataflow/propagation/install/string/index.js +2 -2
- package/lib/dataflow/propagation/install/string/match-all.js +2 -1
- package/lib/dataflow/propagation/install/string/match-all.test.js +13 -0
- package/lib/dataflow/propagation/install/string/match.js +11 -10
- package/lib/dataflow/propagation/install/string/match.test.js +13 -0
- package/lib/dataflow/propagation/install/string/replace.js +15 -9
- package/lib/dataflow/propagation/install/string/replace.test.js +13 -0
- package/lib/dataflow/propagation/install/string/slice.js +2 -1
- package/lib/dataflow/propagation/install/string/slice.test.js +13 -0
- package/lib/dataflow/propagation/install/string/split.js +2 -1
- package/lib/dataflow/propagation/install/string/split.test.js +13 -0
- package/lib/dataflow/propagation/install/string/substring.js +2 -1
- package/lib/dataflow/propagation/install/string/substring.test.js +13 -0
- package/lib/dataflow/propagation/install/string/trim.js +4 -1
- package/lib/dataflow/propagation/install/string/trim.test.js +13 -0
- package/lib/dataflow/propagation/install/unescape.js +5 -8
- package/lib/dataflow/propagation/install/unescape.test.js +2 -2
- package/lib/dataflow/propagation/install/url/domain-parsers.js +4 -5
- package/lib/dataflow/propagation/install/url/domain-parsers.test.js +2 -2
- package/lib/dataflow/propagation/install/url/parse.js +3 -2
- package/lib/dataflow/propagation/install/url/parse.test.js +2 -2
- package/lib/dataflow/propagation/install/url/searchParams.js +5 -5
- package/lib/dataflow/propagation/install/url/searchParams.test.js +2 -2
- package/lib/dataflow/propagation/install/url/url.js +6 -3
- package/lib/dataflow/propagation/install/url/url.test.js +2 -2
- package/lib/dataflow/propagation/install/util-format.js +7 -6
- package/lib/dataflow/propagation/install/util-format.test.js +2 -2
- package/lib/dataflow/propagation/install/validator/hooks.js +7 -2
- package/lib/dataflow/sinks/install/child-process.js +1 -1
- package/lib/dataflow/sinks/install/child-process.test.js +1 -1
- package/lib/dataflow/sinks/install/fs.js +1 -1
- package/lib/dataflow/sinks/install/fs.test.js +1 -1
- package/lib/dataflow/sinks/install/function.js +1 -1
- package/lib/dataflow/sinks/install/http/request.js +2 -1
- package/lib/dataflow/sinks/install/http/request.test.js +1 -1
- package/lib/dataflow/sinks/install/http/server-response.test.js +3 -5
- package/lib/dataflow/sinks/install/restify.js +1 -1
- package/lib/dataflow/sinks/install/vm.js +4 -2
- package/lib/dataflow/sinks/install/vm.test.js +1 -1
- package/lib/dataflow/sources/handler.js +6 -3
- package/lib/dataflow/sources/handler.test.js +38 -0
- package/lib/dataflow/sources/install/body-parser1.test.js +4 -4
- package/lib/dataflow/sources/install/busboy.js +8 -3
- package/lib/dataflow/sources/install/busboy.test.js +2 -2
- package/lib/dataflow/sources/install/cookie-parser1.test.js +2 -2
- package/lib/dataflow/sources/install/express/params.js +14 -11
- package/lib/dataflow/sources/install/express/params.test.js +5 -7
- package/lib/dataflow/sources/install/express/parsedUrl.js +3 -2
- package/lib/dataflow/sources/install/fastify/fastify.js +7 -6
- package/lib/dataflow/sources/install/fastify/fastify.test.js +2 -2
- package/lib/dataflow/sources/install/formidable1.js +7 -6
- package/lib/dataflow/sources/install/formidable1.test.js +2 -2
- package/lib/dataflow/sources/install/hapi/hapi.js +8 -10
- package/lib/dataflow/sources/install/hapi/hapi.test.js +0 -1
- package/lib/dataflow/sources/install/http.js +20 -16
- package/lib/dataflow/sources/install/http.test.js +28 -34
- package/lib/dataflow/sources/install/koa/koa-bodyparsers.js +7 -7
- package/lib/dataflow/sources/install/koa/koa-bodyparsers.test.js +3 -4
- package/lib/dataflow/sources/install/koa/koa-multer.js +8 -4
- package/lib/dataflow/sources/install/koa/koa-routers.js +7 -6
- package/lib/dataflow/sources/install/koa/koa-routers.test.js +2 -2
- package/lib/dataflow/sources/install/koa/koa2.js +7 -3
- package/lib/dataflow/sources/install/koa/koa2.test.js +1 -1
- package/lib/dataflow/sources/install/multer1.js +6 -2
- package/lib/dataflow/sources/install/qs6.js +1 -1
- package/lib/dataflow/sources/install/querystring.js +1 -1
- package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.js +1 -4
- package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.test.js +6 -8
- package/lib/dataflow/sources/install/restify/jsonBodyParser.js +0 -1
- package/lib/dataflow/sources/install/restify/jsonBodyParser.test.js +4 -8
- package/lib/dataflow/sources/install/restify/router.test.js +2 -2
- package/lib/dataflow/tag-utils.js +1 -1
- package/lib/dataflow/tracker.js +1 -1
- package/lib/dataflow/utils/is-safe-content-type.js +3 -2
- package/lib/event-factory.js +4 -4
- package/lib/event-factory.test.js +19 -14
- package/lib/get-policy.js +2 -2
- package/lib/index.d.ts +11 -6
- package/lib/index.js +18 -7
- package/lib/index.test.js +4 -0
- package/lib/make-source-context.js +37 -28
- package/lib/make-source-context.test.js +7 -7
- package/lib/response-scanning/handlers/index.js +7 -5
- package/lib/response-scanning/handlers/utils.js +11 -8
- package/lib/response-scanning/install/http.js +1 -1
- package/lib/sampler.js +136 -0
- package/lib/sampler.test.js +296 -0
- package/lib/session-configuration/install/express-session.js +1 -1
- package/lib/session-configuration/install/fastify-cookie.js +1 -1
- package/package.json +10 -10
|
@@ -15,19 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
} = require('
|
|
21
|
-
const {
|
|
22
|
-
createFullLengthCopyTags
|
|
23
|
-
} = require('../../tag-utils');
|
|
18
|
+
const { DataflowTag: { WEAK_URL_ENCODED } } = require('@contrast/common');
|
|
19
|
+
const { InstrumentationType: { PROPAGATOR } } = require('../../../constants');
|
|
20
|
+
const { createFullLengthCopyTags } = require('../../tag-utils');
|
|
24
21
|
const { patchType, createObjectLabel } = require('../common');
|
|
25
22
|
|
|
26
23
|
module.exports = function(core) {
|
|
27
24
|
const {
|
|
28
|
-
scopes: { sources, instrumentation },
|
|
29
25
|
patcher,
|
|
30
26
|
assess: {
|
|
27
|
+
getSourceContext,
|
|
31
28
|
eventFactory: { createPropagationEvent },
|
|
32
29
|
dataflow: { tracker }
|
|
33
30
|
}
|
|
@@ -42,7 +39,7 @@ module.exports = function(core) {
|
|
|
42
39
|
patchType,
|
|
43
40
|
post(data) {
|
|
44
41
|
const { args, result, hooked, orig } = data;
|
|
45
|
-
if (!result || !args[0] || !
|
|
42
|
+
if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
|
|
46
43
|
|
|
47
44
|
const argInfo = tracker.getData(args[0]);
|
|
48
45
|
|
|
@@ -58,12 +58,12 @@ describe('assess dataflow propagation unescape', function () {
|
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
it('will not propagate if there is no assess context', function () {
|
|
61
|
+
it('will not propagate if there is no assess policy in request context', function () {
|
|
62
62
|
simulateRequestScope(function () {
|
|
63
63
|
const value = trackString('%3Ftest%3Dstr');
|
|
64
64
|
const result = unescape(value);
|
|
65
65
|
expect(tracker.getData(result)).to.be.null;
|
|
66
|
-
}, {});
|
|
66
|
+
}, { assess: { policy: null } });
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
it('will not propagate if there instrumentation is locked', function () {
|
|
@@ -15,17 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
} = require('../../../tag-utils');
|
|
18
|
+
const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
|
|
19
|
+
const { createFullLengthCopyTags } = require('../../../tag-utils');
|
|
21
20
|
const { patchType, createModuleLabel } = require('../../common');
|
|
22
21
|
|
|
23
22
|
module.exports = function(core) {
|
|
24
23
|
const {
|
|
25
|
-
scopes: { sources, instrumentation },
|
|
26
24
|
patcher,
|
|
27
25
|
depHooks,
|
|
28
26
|
assess: {
|
|
27
|
+
getSourceContext,
|
|
29
28
|
eventFactory: { createPropagationEvent },
|
|
30
29
|
dataflow: { tracker }
|
|
31
30
|
}
|
|
@@ -42,7 +41,7 @@ module.exports = function(core) {
|
|
|
42
41
|
patchType,
|
|
43
42
|
post(data) {
|
|
44
43
|
const { args, result, hooked, orig } = data;
|
|
45
|
-
if (!result || !args[0] || !
|
|
44
|
+
if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
|
|
46
45
|
|
|
47
46
|
const argInfo = tracker.getData(args[0]);
|
|
48
47
|
|
|
@@ -43,12 +43,12 @@ describe('assess dataflow propagation url domain-parsers', function () {
|
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
it('will not propagate if there is no assess context', function () {
|
|
46
|
+
it('will not propagate if there is no assess store in request context', function () {
|
|
47
47
|
simulateRequestScope(function () {
|
|
48
48
|
const value = trackString('foo');
|
|
49
49
|
const result = url.domainToASCII(value);
|
|
50
50
|
expect(tracker.getData(result)).to.be.null;
|
|
51
|
-
}, {});
|
|
51
|
+
}, { assess: { policy: null } });
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
it('will not propagate if there instrumentation is locked', function () {
|
|
@@ -15,14 +15,15 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
+
const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
|
|
18
19
|
const { patchType } = require('../../common');
|
|
19
20
|
|
|
20
21
|
module.exports = function(core) {
|
|
21
22
|
const {
|
|
22
|
-
scopes: { sources, instrumentation },
|
|
23
23
|
patcher,
|
|
24
24
|
depHooks,
|
|
25
25
|
assess: {
|
|
26
|
+
getSourceContext,
|
|
26
27
|
inspect, // todo: remove
|
|
27
28
|
eventFactory: { createPropagationEvent },
|
|
28
29
|
dataflow: { tracker }
|
|
@@ -88,7 +89,7 @@ module.exports = function(core) {
|
|
|
88
89
|
patchType,
|
|
89
90
|
post(data) {
|
|
90
91
|
const { args, result, hooked, orig } = data;
|
|
91
|
-
if (!result || !args[0] || !
|
|
92
|
+
if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
|
|
92
93
|
|
|
93
94
|
const [url, parseQueryString] = args;
|
|
94
95
|
const argInfo = tracker.getData(url);
|
|
@@ -67,14 +67,14 @@ describe('assess dataflow propagation url.parse', function () {
|
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
it('will not propagate if there is no assess context', function () {
|
|
70
|
+
it('will not propagate if there is no assess policy in request context', function () {
|
|
71
71
|
simulateRequestScope(function () {
|
|
72
72
|
const value = trackString('foo');
|
|
73
73
|
const result = new url.parse('http://'.concat(value, ':3000/path'));
|
|
74
74
|
keys.forEach((key) => {
|
|
75
75
|
expect(tracker.getData(result[key])).to.be.null;
|
|
76
76
|
});
|
|
77
|
-
}, {});
|
|
77
|
+
}, { assess: { policy: null } });
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
it('will not propagate if there instrumentation is locked', function () {
|
|
@@ -15,17 +15,18 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
-
const {
|
|
19
|
-
const {
|
|
18
|
+
const { isString, primordials: { StringPrototypeConcat, StringPrototypeReplaceAll } } = require('@contrast/common');
|
|
19
|
+
const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
|
|
20
20
|
const { createAppendTags } = require('../../../tag-utils');
|
|
21
|
+
const { patchType } = require('../../common');
|
|
21
22
|
|
|
22
23
|
module.exports = function(core) {
|
|
23
24
|
const {
|
|
24
|
-
scopes: { sources, instrumentation },
|
|
25
25
|
patcher,
|
|
26
26
|
depHooks,
|
|
27
27
|
assess: {
|
|
28
28
|
inspect, // todo: remove
|
|
29
|
+
getSourceContext,
|
|
29
30
|
eventFactory: { createPropagationEvent },
|
|
30
31
|
dataflow: { tracker }
|
|
31
32
|
}
|
|
@@ -60,7 +61,6 @@ module.exports = function(core) {
|
|
|
60
61
|
return core.assess.dataflow.propagation.urlInstrumentation.searchParams = {
|
|
61
62
|
install() {
|
|
62
63
|
depHooks.resolve({ name: 'url' }, (url) => {
|
|
63
|
-
|
|
64
64
|
const name = 'url.URLSearchParams';
|
|
65
65
|
|
|
66
66
|
patcher.patch(url, 'URLSearchParams', {
|
|
@@ -68,7 +68,7 @@ module.exports = function(core) {
|
|
|
68
68
|
patchType,
|
|
69
69
|
post(data) {
|
|
70
70
|
const { args, obj, result } = data;
|
|
71
|
-
if (!result || !args[0] || !
|
|
71
|
+
if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
|
|
72
72
|
|
|
73
73
|
const [params] = args;
|
|
74
74
|
|
|
@@ -40,14 +40,14 @@ describe('assess dataflow propagation url.URLSearchParams', function () {
|
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
it('will not propagate if there is no assess context', function () {
|
|
43
|
+
it('will not propagate if there is no assess policy in request context', function () {
|
|
44
44
|
simulateRequestScope(function () {
|
|
45
45
|
const value = trackString('foo');
|
|
46
46
|
const result = new url.URLSearchParams('?query='.concat(value));
|
|
47
47
|
const input = result.get('query');
|
|
48
48
|
expect(input).to.be.equal('foo');
|
|
49
49
|
expect(tracker.getData(input)).to.be.null;
|
|
50
|
-
}, {});
|
|
50
|
+
}, { assess: { policy: null } });
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
it('will not propagate if instrumentation is locked', function () {
|
|
@@ -15,14 +15,17 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
+
const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
|
|
18
19
|
const { patchType } = require('../../common');
|
|
19
20
|
|
|
21
|
+
const { primordials: { StringPrototypeSplit } } = require('@contrast/common');
|
|
22
|
+
|
|
20
23
|
module.exports = function(core) {
|
|
21
24
|
const {
|
|
22
|
-
scopes: { sources, instrumentation },
|
|
23
25
|
patcher,
|
|
24
26
|
depHooks,
|
|
25
27
|
assess: {
|
|
28
|
+
getSourceContext,
|
|
26
29
|
inspect, // todo: remove
|
|
27
30
|
eventFactory: { createPropagationEvent },
|
|
28
31
|
dataflow: { tracker }
|
|
@@ -91,7 +94,7 @@ module.exports = function(core) {
|
|
|
91
94
|
patchType,
|
|
92
95
|
post(data) {
|
|
93
96
|
const { args, result } = data;
|
|
94
|
-
if (!result || !args[0] || !
|
|
97
|
+
if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
|
|
95
98
|
|
|
96
99
|
const [input, basename] = args;
|
|
97
100
|
let url = input;
|
|
@@ -143,7 +146,7 @@ module.exports = function(core) {
|
|
|
143
146
|
if (part !== 'null') {
|
|
144
147
|
|
|
145
148
|
if (key === 'origin') {
|
|
146
|
-
const [protocol, originWithoutProtocol] =
|
|
149
|
+
const [protocol, originWithoutProtocol] = StringPrototypeSplit.call(part, new RegExp('(?<=//)'));
|
|
147
150
|
const idx1 = href.indexOf(protocol);
|
|
148
151
|
const idx2 = href.indexOf(originWithoutProtocol, idx - 1);
|
|
149
152
|
substr = href.substring(idx1, idx1 + protocol.length).concat(href.substring(idx2, idx2 + originWithoutProtocol.length));
|
|
@@ -67,14 +67,14 @@ describe('assess dataflow propagation url.URL', function () {
|
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
it('will not propagate if there is no assess context', function () {
|
|
70
|
+
it('will not propagate if there is no assess policy in request context', function () {
|
|
71
71
|
simulateRequestScope(function () {
|
|
72
72
|
const value = trackString('foo');
|
|
73
73
|
const result = new url.URL('http://'.concat(value, ':3000/path'));
|
|
74
74
|
keys.forEach((key) => {
|
|
75
75
|
expect(tracker.getData(result[key])).to.be.null;
|
|
76
76
|
});
|
|
77
|
-
}, {});
|
|
77
|
+
}, { assess: { policy: null } });
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
it('will not propagate if there instrumentation is locked', function () {
|
|
@@ -15,16 +15,17 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
-
const {
|
|
19
|
-
const {
|
|
18
|
+
const { isString, primordials: { StringPrototypeMatch, StringPrototypeToLowerCase } } = require('@contrast/common');
|
|
19
|
+
const { InstrumentationType: { PROPAGATOR } } = require('../../../constants');
|
|
20
20
|
const { createAppendTags } = require('../../tag-utils');
|
|
21
|
+
const { patchType } = require('../common');
|
|
21
22
|
|
|
22
23
|
module.exports = function(core) {
|
|
23
24
|
const {
|
|
24
|
-
scopes: { sources, instrumentation },
|
|
25
25
|
patcher,
|
|
26
26
|
depHooks,
|
|
27
27
|
assess: {
|
|
28
|
+
getSourceContext,
|
|
28
29
|
eventFactory: { createPropagationEvent },
|
|
29
30
|
dataflow: { tracker }
|
|
30
31
|
}
|
|
@@ -40,13 +41,13 @@ module.exports = function(core) {
|
|
|
40
41
|
patchType,
|
|
41
42
|
post(data) {
|
|
42
43
|
const { args, result, hooked, orig } = data;
|
|
43
|
-
if (!result || !args[0] || !isString(args[0]) || !
|
|
44
|
+
if (!result || !args[0] || !isString(args[0]) || !getSourceContext(PROPAGATOR)) return;
|
|
44
45
|
|
|
45
46
|
let idx = 0;
|
|
46
47
|
let newTags = {};
|
|
47
48
|
const history = [];
|
|
48
49
|
const eventArgs = [];
|
|
49
|
-
const formatChars = args[0].includes('%') ? args[0]
|
|
50
|
+
const formatChars = args[0].includes('%') ? StringPrototypeMatch.call(args[0], /[^%]+/g).map((x) => x[0]) : [];
|
|
50
51
|
let i = 0;
|
|
51
52
|
|
|
52
53
|
if (formatChars.length > 0) {
|
|
@@ -61,7 +62,7 @@ module.exports = function(core) {
|
|
|
61
62
|
|
|
62
63
|
if (formatChar === 'j') {
|
|
63
64
|
arg = JSON.stringify(arg);
|
|
64
|
-
} else if (
|
|
65
|
+
} else if (StringPrototypeToLowerCase.call(formatChar) === 'o') {
|
|
65
66
|
// TO-DO: NODE-3235
|
|
66
67
|
}
|
|
67
68
|
}
|
|
@@ -25,12 +25,12 @@ describe('assess dataflow propagation util.format', function () {
|
|
|
25
25
|
core.depHooks.resolve.yield(util);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
it('will not propagate if there is no assess context', function () {
|
|
28
|
+
it('will not propagate if there is no assess policy in request context', function () {
|
|
29
29
|
simulateRequestScope(function () {
|
|
30
30
|
const value = trackString('foo');
|
|
31
31
|
const result = util.format('%s:%s', value, 'bar');
|
|
32
32
|
expect(tracker.getData(result)).to.be.null;
|
|
33
|
-
}, {});
|
|
33
|
+
}, { assess: { policy: null } });
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it('will not propagate if there instrumentation is locked', function () {
|
|
@@ -26,6 +26,7 @@ module.exports = function (core) {
|
|
|
26
26
|
depHooks,
|
|
27
27
|
patcher,
|
|
28
28
|
assess: {
|
|
29
|
+
getSourceContext,
|
|
29
30
|
eventFactory: { createPropagationEvent },
|
|
30
31
|
dataflow: { tracker }
|
|
31
32
|
}
|
|
@@ -73,7 +74,8 @@ module.exports = function (core) {
|
|
|
73
74
|
const matches = validator === 'matches';
|
|
74
75
|
if (
|
|
75
76
|
data.result &&
|
|
76
|
-
(!matches || (matches && core.config.assess.trust_custom_validators))
|
|
77
|
+
(!matches || (matches && core.config.assess.trust_custom_validators)) &&
|
|
78
|
+
getSourceContext()
|
|
77
79
|
) {
|
|
78
80
|
const trackingData = tracker.getData(data.args[0]);
|
|
79
81
|
if (trackingData) {
|
|
@@ -104,7 +106,7 @@ module.exports = function (core) {
|
|
|
104
106
|
name: `validator.${untracker}`,
|
|
105
107
|
patchType,
|
|
106
108
|
post(data) {
|
|
107
|
-
if (data.result) {
|
|
109
|
+
if (data.result && getSourceContext()) {
|
|
108
110
|
const trackingData = tracker.getData(data.args[0]);
|
|
109
111
|
if (trackingData) {
|
|
110
112
|
tracker.untrack(data.args[0]);
|
|
@@ -121,6 +123,7 @@ module.exports = function (core) {
|
|
|
121
123
|
name: `validator.${sanitizer}`,
|
|
122
124
|
patchType,
|
|
123
125
|
post(data) {
|
|
126
|
+
if (!getSourceContext()) return;
|
|
124
127
|
const trackingData = tracker.getData(data.args[0]);
|
|
125
128
|
if (trackingData) {
|
|
126
129
|
const newTags = {};
|
|
@@ -153,6 +156,8 @@ module.exports = function (core) {
|
|
|
153
156
|
name: `validator.${method}`,
|
|
154
157
|
patchType,
|
|
155
158
|
post(data) {
|
|
159
|
+
if (!getSourceContext()) return;
|
|
160
|
+
|
|
156
161
|
const options = data.args[1];
|
|
157
162
|
const trackingData = tracker.getData(data.args[0]);
|
|
158
163
|
|
|
@@ -6,7 +6,7 @@ const {
|
|
|
6
6
|
const sinon = require('sinon');
|
|
7
7
|
const { expect } = require('chai');
|
|
8
8
|
const { initAssessFixture } = require('@contrast/test/fixtures');
|
|
9
|
-
const { UtilInspect } = require('@contrast/common');
|
|
9
|
+
const { primordials: { UtilInspect } } = require('@contrast/common');
|
|
10
10
|
|
|
11
11
|
describe('assess dataflow sinks child_process', function () {
|
|
12
12
|
let core, child_process, simulateRequestScope, trackString, tracker, reportFindings;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const sinon = require('sinon');
|
|
4
4
|
const { expect } = require('chai');
|
|
5
|
-
const { FS_METHODS, ArrayPrototypeJoin, UtilInspect } = require('@contrast/common');
|
|
5
|
+
const { FS_METHODS, primordials: { ArrayPrototypeJoin, UtilInspect } } = require('@contrast/common');
|
|
6
6
|
const { initAssessFixture } = require('@contrast/test/fixtures');
|
|
7
7
|
|
|
8
8
|
describe('assess dataflow sinks path-traversal', function () {
|
|
@@ -27,6 +27,7 @@ const {
|
|
|
27
27
|
LIMITED_CHARS
|
|
28
28
|
},
|
|
29
29
|
Rule: { SSRF: ruleId },
|
|
30
|
+
primordials: { RegExpPrototypeExec }
|
|
30
31
|
} = require('@contrast/common');
|
|
31
32
|
const { InstrumentationType: { RULE } } = require('../../../../constants');
|
|
32
33
|
const { createAppendTags } = require('../../../tag-utils');
|
|
@@ -84,7 +85,7 @@ module.exports = function(core) {
|
|
|
84
85
|
function containsTrustedLib(stack) {
|
|
85
86
|
for (const { file } of stack) {
|
|
86
87
|
for (const trusted of trustedLibs) {
|
|
87
|
-
if (
|
|
88
|
+
if (RegExpPrototypeExec.call(trusted, file)) {
|
|
88
89
|
return true;
|
|
89
90
|
}
|
|
90
91
|
}
|
|
@@ -73,17 +73,15 @@ describe('assess dataflow sinks http, http2, spdy', function () {
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
it('skips instrumentation if the content-type is safe', function () {
|
|
76
|
-
const store = {
|
|
77
|
-
assess: { responseData: { contentType: 'application/json' } },
|
|
78
|
-
};
|
|
79
|
-
|
|
80
76
|
simulateRequestScope(function () {
|
|
77
|
+
core.scopes.sources.getStore().assess.responseData.contentType = 'application/json';
|
|
78
|
+
|
|
81
79
|
const str = trackString('hello world');
|
|
82
80
|
const { extern } = tracker.getData(str);
|
|
83
81
|
|
|
84
82
|
response[method](extern);
|
|
85
83
|
expect(reportFindings).to.not.have.been.called;
|
|
86
|
-
}
|
|
84
|
+
});
|
|
87
85
|
});
|
|
88
86
|
|
|
89
87
|
it('skips instrumentation if the string is safe', function () {
|
|
@@ -26,7 +26,7 @@ const {
|
|
|
26
26
|
URL_ENCODED,
|
|
27
27
|
},
|
|
28
28
|
isString,
|
|
29
|
-
ArrayPrototypeJoin,
|
|
29
|
+
primordials: { ArrayPrototypeJoin },
|
|
30
30
|
} = require('@contrast/common');
|
|
31
31
|
const { InstrumentationType: { RULE } } = require('../../../constants');
|
|
32
32
|
const { createAppendTags } = require('../../tag-utils');
|
|
@@ -27,8 +27,10 @@ const {
|
|
|
27
27
|
Rule: { UNSAFE_CODE_EXECUTION: ruleId },
|
|
28
28
|
isNonEmptyObject,
|
|
29
29
|
isString,
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
primordials: {
|
|
31
|
+
ArrayPrototypeJoin,
|
|
32
|
+
StringPrototypeSplit,
|
|
33
|
+
},
|
|
32
34
|
traverseValues,
|
|
33
35
|
} = require('@contrast/common');
|
|
34
36
|
const { InstrumentationType: { RULE } } = require('../../../constants');
|
|
@@ -5,7 +5,7 @@ const { expect } = require('chai');
|
|
|
5
5
|
const {
|
|
6
6
|
DataflowTag: { UNTRUSTED, CUSTOM_VALIDATED },
|
|
7
7
|
Rule: { UNSAFE_CODE_EXECUTION },
|
|
8
|
-
UtilInspect,
|
|
8
|
+
primordials: { UtilInspect },
|
|
9
9
|
} = require('@contrast/common');
|
|
10
10
|
const { initAssessFixture } = require('@contrast/test/fixtures');
|
|
11
11
|
|
|
@@ -19,7 +19,10 @@ const {
|
|
|
19
19
|
InputType,
|
|
20
20
|
DataflowTag,
|
|
21
21
|
isString,
|
|
22
|
-
|
|
22
|
+
primordials: {
|
|
23
|
+
ArrayPrototypeJoin,
|
|
24
|
+
StringPrototypeToLowerCase
|
|
25
|
+
}
|
|
23
26
|
} = require('@contrast/common');
|
|
24
27
|
|
|
25
28
|
module.exports = function (core) {
|
|
@@ -55,7 +58,7 @@ module.exports = function (core) {
|
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
if (inputType === InputType.HEADER &&
|
|
61
|
+
if (inputType === InputType.HEADER && StringPrototypeToLowerCase.call(fieldName) === 'referer') {
|
|
59
62
|
tags[DataflowTag.HEADER] = [0, stop];
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -63,7 +66,7 @@ module.exports = function (core) {
|
|
|
63
66
|
};
|
|
64
67
|
|
|
65
68
|
sources.createStacktrace = function (stacktraceOpts) {
|
|
66
|
-
return config.assess.stacktraces === 'NONE'
|
|
69
|
+
return config.assess.stacktraces === 'NONE' || config.assess.stacktraces === 'SINK'
|
|
67
70
|
? emptyStack
|
|
68
71
|
: createSnapshot(stacktraceOpts)();
|
|
69
72
|
};
|
|
@@ -139,6 +139,44 @@ describe('assess dataflow sources handler', function () {
|
|
|
139
139
|
});
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
+
['SINK', 'NONE'].forEach((option) => {
|
|
143
|
+
it(`does not capture stacktrace for assess.stacktraces=${option}`, function() {
|
|
144
|
+
simulateRequestScope(() => {
|
|
145
|
+
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
146
|
+
core.config.assess.stacktraces = option;
|
|
147
|
+
const trackedObj = sources.handle({
|
|
148
|
+
name: 'test-source-name',
|
|
149
|
+
inputType: InputType.QUERYSTRING,
|
|
150
|
+
data: { prop1: 'foo' },
|
|
151
|
+
sourceContext
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const trackData = tracker.getData(trackedObj.prop1);
|
|
155
|
+
expect(trackData.stack).to.deep.equal([]);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
['SOME', 'ALL'].forEach((option) => {
|
|
161
|
+
it(`captures stacktrace for assess.stacktraces=${option}`, function() {
|
|
162
|
+
simulateRequestScope(() => {
|
|
163
|
+
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
164
|
+
core.config.assess.stacktraces = option;
|
|
165
|
+
const trackedObj = sources.handle({
|
|
166
|
+
name: 'test-source-name',
|
|
167
|
+
inputType: InputType.QUERYSTRING,
|
|
168
|
+
data: { prop1: 'foo' },
|
|
169
|
+
sourceContext
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const trackData = tracker.getData(trackedObj.prop1);
|
|
173
|
+
expect(trackData.stack).to.be.instanceOf(Array);
|
|
174
|
+
expect(trackData.stack.length).to.be.greaterThan(0);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
|
|
142
180
|
it('traverses objects and tracks string values', function () {
|
|
143
181
|
simulateRequestScope(() => {
|
|
144
182
|
const sourceContext = core.scopes.sources.getStore()?.assess;
|
|
@@ -105,7 +105,7 @@ describe('assess dataflow sources body-parser v1', function () {
|
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
it('does not handle the request when
|
|
108
|
+
it('does not handle the request when there is no assess policy in request context', function () {
|
|
109
109
|
const middleware = bodyParser('text');
|
|
110
110
|
|
|
111
111
|
simulateRequestScope(() => {
|
|
@@ -116,7 +116,7 @@ describe('assess dataflow sources body-parser v1', function () {
|
|
|
116
116
|
{ funcKey: 'assess-dataflow-source:body-parser.bodyParser' },
|
|
117
117
|
'unable to handle source. Missing `sourceContext`'
|
|
118
118
|
);
|
|
119
|
-
}, {});
|
|
119
|
+
}, { assess: { policy: null } });
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
it('does not handle the request when already tracked', function () {
|
|
@@ -205,7 +205,7 @@ describe('assess dataflow sources body-parser v1', function () {
|
|
|
205
205
|
});
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
it('does not handle the request when
|
|
208
|
+
it('does not handle the request when there is in context', function () {
|
|
209
209
|
simulateRequestScope(() => {
|
|
210
210
|
middleware(req, res, next);
|
|
211
211
|
|
|
@@ -214,7 +214,7 @@ describe('assess dataflow sources body-parser v1', function () {
|
|
|
214
214
|
{ funcKey: `assess-dataflow-source:body-parser.${method}.${method}Parser` },
|
|
215
215
|
'unable to handle source. Missing `sourceContext`',
|
|
216
216
|
);
|
|
217
|
-
}, {});
|
|
217
|
+
}, { assess: { policy: null } });
|
|
218
218
|
});
|
|
219
219
|
|
|
220
220
|
it('does not handle the request when already tracked', function () {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
18
|
const { InputType } = require('@contrast/common');
|
|
19
|
+
const { InstrumentationType: { SOURCE } } = require('../../../constants');
|
|
19
20
|
const { patchType } = require('../common');
|
|
20
21
|
|
|
21
22
|
const inputType = InputType.MULTIPART_VALUE;
|
|
@@ -26,16 +27,20 @@ module.exports = (core) => {
|
|
|
26
27
|
depHooks,
|
|
27
28
|
patcher,
|
|
28
29
|
logger,
|
|
29
|
-
assess: {
|
|
30
|
+
assess: {
|
|
31
|
+
getSourceContext,
|
|
32
|
+
dataflow: {
|
|
33
|
+
sources,
|
|
34
|
+
}
|
|
35
|
+
},
|
|
30
36
|
} = core;
|
|
31
37
|
|
|
32
38
|
function createPreHook(finalEventName) {
|
|
33
39
|
return function (data) {
|
|
34
40
|
const { orig, hooked, funcKey } = data;
|
|
35
|
-
const sourceContext =
|
|
41
|
+
const sourceContext = getSourceContext(SOURCE);
|
|
36
42
|
|
|
37
43
|
if (!sourceContext) {
|
|
38
|
-
logger.error({ inputType, funcKey }, 'unable to handle source. Missing `sourceContext`');
|
|
39
44
|
return;
|
|
40
45
|
}
|
|
41
46
|
|
|
@@ -110,12 +110,12 @@ describe('assess dataflow sources busboy', function () {
|
|
|
110
110
|
);
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
it('does not call `.handle` when
|
|
113
|
+
it('does not call `.handle` when there is no assess policy in request context', function () {
|
|
114
114
|
simulateRequestScope(() => {
|
|
115
115
|
emitMethodVersions[version]('field', 'field1', 'value1');
|
|
116
116
|
emitMethodVersions[version]('field', 'field2', 'value2');
|
|
117
117
|
emitMethodVersions[version](finalEvent);
|
|
118
|
-
}, {});
|
|
118
|
+
}, { assess: { policy: null } });
|
|
119
119
|
|
|
120
120
|
expect(sources.handle).not.to.have.been.called;
|
|
121
121
|
});
|