@contrast/assess 1.46.0 → 1.46.2
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/package.json +14 -11
- package/lib/crypto-analysis/install/crypto.test.js +0 -146
- package/lib/crypto-analysis/install/math.test.js +0 -65
- package/lib/dataflow/index.test.js +0 -36
- package/lib/dataflow/propagation/index.test.js +0 -103
- package/lib/dataflow/propagation/install/JSON/index.test.js +0 -50
- package/lib/dataflow/propagation/install/JSON/parse-fn.test.js +0 -232
- package/lib/dataflow/propagation/install/JSON/parse.test.js +0 -968
- package/lib/dataflow/propagation/install/JSON/stringify.test.js +0 -265
- package/lib/dataflow/propagation/install/array-prototype-join.test.js +0 -106
- package/lib/dataflow/propagation/install/buffer.test.js +0 -112
- package/lib/dataflow/propagation/install/contrast-methods/add.test.js +0 -94
- package/lib/dataflow/propagation/install/contrast-methods/index.test.js +0 -49
- package/lib/dataflow/propagation/install/contrast-methods/number.test.js +0 -50
- package/lib/dataflow/propagation/install/contrast-methods/string.test.js +0 -148
- package/lib/dataflow/propagation/install/contrast-methods/tag.test.js +0 -145
- package/lib/dataflow/propagation/install/decode-uri-component.test.js +0 -78
- package/lib/dataflow/propagation/install/ejs/escape-xml.test.js +0 -69
- package/lib/dataflow/propagation/install/ejs/template.test.js +0 -62
- package/lib/dataflow/propagation/install/encode-uri.test.js +0 -83
- package/lib/dataflow/propagation/install/escape-html.test.js +0 -71
- package/lib/dataflow/propagation/install/escape.test.js +0 -73
- package/lib/dataflow/propagation/install/fastify-send.test.js +0 -42
- package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.test.js +0 -71
- package/lib/dataflow/propagation/install/isnumeric-0.test.js +0 -58
- package/lib/dataflow/propagation/install/joi/any.test.js +0 -270
- package/lib/dataflow/propagation/install/joi/array.test.js +0 -912
- package/lib/dataflow/propagation/install/joi/boolean.test.js +0 -103
- package/lib/dataflow/propagation/install/joi/expression.test.js +0 -76
- package/lib/dataflow/propagation/install/joi/index.test.js +0 -39
- package/lib/dataflow/propagation/install/joi/number.test.js +0 -103
- package/lib/dataflow/propagation/install/joi/object.test.js +0 -119
- package/lib/dataflow/propagation/install/joi/ref.test.js +0 -607
- package/lib/dataflow/propagation/install/joi/string-schema.test.js +0 -513
- package/lib/dataflow/propagation/install/mongoose/index.test.js +0 -42
- package/lib/dataflow/propagation/install/mongoose/schema-map.test.js +0 -348
- package/lib/dataflow/propagation/install/mongoose/schema-mixed.test.js +0 -511
- package/lib/dataflow/propagation/install/mongoose/schema-string.test.js +0 -199
- package/lib/dataflow/propagation/install/mustache-escape.test.js +0 -62
- package/lib/dataflow/propagation/install/mysql-connection-escape.test.js +0 -74
- package/lib/dataflow/propagation/install/parse-int.test.js +0 -48
- package/lib/dataflow/propagation/install/path/basename.test.js +0 -143
- package/lib/dataflow/propagation/install/path/dirname.test.js +0 -167
- package/lib/dataflow/propagation/install/path/extname.test.js +0 -141
- package/lib/dataflow/propagation/install/path/format.test.js +0 -250
- package/lib/dataflow/propagation/install/path/index.test.js +0 -45
- package/lib/dataflow/propagation/install/path/join-and-resolve.test.js +0 -485
- package/lib/dataflow/propagation/install/path/normalize.test.js +0 -176
- package/lib/dataflow/propagation/install/path/parse.test.js +0 -238
- package/lib/dataflow/propagation/install/path/relative.test.js +0 -239
- package/lib/dataflow/propagation/install/path/toNamespacedPath.test.js +0 -158
- package/lib/dataflow/propagation/install/pug/index.test.js +0 -55
- package/lib/dataflow/propagation/install/pug-runtime-escape.test.js +0 -69
- package/lib/dataflow/propagation/install/querystring/escape.test.js +0 -63
- package/lib/dataflow/propagation/install/querystring/index.test.js +0 -40
- package/lib/dataflow/propagation/install/querystring/parse.test.js +0 -272
- package/lib/dataflow/propagation/install/querystring/stringify.test.js +0 -301
- package/lib/dataflow/propagation/install/reg-exp-prototype-exec.test.js +0 -283
- package/lib/dataflow/propagation/install/send.test.js +0 -63
- package/lib/dataflow/propagation/install/sequelize/query-generator.test.js +0 -74
- package/lib/dataflow/propagation/install/sequelize/sql-string.test.js +0 -119
- package/lib/dataflow/propagation/install/sql-template-strings.test.js +0 -100
- package/lib/dataflow/propagation/install/string/concat.test.js +0 -145
- package/lib/dataflow/propagation/install/string/format-methods.test.js +0 -74
- package/lib/dataflow/propagation/install/string/html-methods.test.js +0 -177
- package/lib/dataflow/propagation/install/string/index.test.js +0 -103
- package/lib/dataflow/propagation/install/string/match-all.test.js +0 -412
- package/lib/dataflow/propagation/install/string/match.test.js +0 -374
- package/lib/dataflow/propagation/install/string/replace.test.js +0 -601
- package/lib/dataflow/propagation/install/string/slice.test.js +0 -278
- package/lib/dataflow/propagation/install/string/split.test.js +0 -513
- package/lib/dataflow/propagation/install/string/substring.test.js +0 -251
- package/lib/dataflow/propagation/install/string/trim.test.js +0 -135
- package/lib/dataflow/propagation/install/unescape.test.js +0 -78
- package/lib/dataflow/propagation/install/url/domain-parsers.test.js +0 -63
- package/lib/dataflow/propagation/install/url/parse.test.js +0 -391
- package/lib/dataflow/propagation/install/url/searchParams.test.js +0 -538
- package/lib/dataflow/propagation/install/url/url.test.js +0 -466
- package/lib/dataflow/propagation/install/util-format.test.js +0 -336
- package/lib/dataflow/propagation/install/validator/hooks.test.js +0 -211
- package/lib/dataflow/sinks/index.test.js +0 -78
- package/lib/dataflow/sinks/install/child-process.test.js +0 -338
- package/lib/dataflow/sinks/install/eval.test.js +0 -95
- package/lib/dataflow/sinks/install/express/index.test.js +0 -33
- package/lib/dataflow/sinks/install/express/reflected-xss.test.js +0 -109
- package/lib/dataflow/sinks/install/express/unvalidated-redirect.test.js +0 -144
- package/lib/dataflow/sinks/install/fastify/index.test.js +0 -32
- package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.test.js +0 -130
- package/lib/dataflow/sinks/install/fs.test.js +0 -138
- package/lib/dataflow/sinks/install/function.test.js +0 -103
- package/lib/dataflow/sinks/install/hapi/index.test.js +0 -32
- package/lib/dataflow/sinks/install/hapi/unvalidated-redirect.test.js +0 -130
- package/lib/dataflow/sinks/install/http/index.test.js +0 -33
- package/lib/dataflow/sinks/install/http/request.test.js +0 -184
- package/lib/dataflow/sinks/install/http/server-response.test.js +0 -160
- package/lib/dataflow/sinks/install/koa/index.test.js +0 -32
- package/lib/dataflow/sinks/install/koa/unvalidated-redirect.test.js +0 -200
- package/lib/dataflow/sinks/install/libxmljs.test.js +0 -158
- package/lib/dataflow/sinks/install/marsdb.test.js +0 -166
- package/lib/dataflow/sinks/install/mongodb.test.js +0 -617
- package/lib/dataflow/sinks/install/mssql.test.js +0 -134
- package/lib/dataflow/sinks/install/mysql.test.js +0 -224
- package/lib/dataflow/sinks/install/node-serialize.test.js +0 -83
- package/lib/dataflow/sinks/install/postgres.test.js +0 -152
- package/lib/dataflow/sinks/install/restify.test.js +0 -140
- package/lib/dataflow/sinks/install/sequelize.test.js +0 -100
- package/lib/dataflow/sinks/install/sqlite3.test.js +0 -118
- package/lib/dataflow/sinks/install/vm.test.js +0 -326
- package/lib/dataflow/sources/handler.test.js +0 -501
- package/lib/dataflow/sources/index.test.js +0 -60
- package/lib/dataflow/sources/install/body-parser1.test.js +0 -244
- package/lib/dataflow/sources/install/busboy.test.js +0 -152
- package/lib/dataflow/sources/install/cookie-parser1.test.js +0 -141
- package/lib/dataflow/sources/install/express/params.test.js +0 -110
- package/lib/dataflow/sources/install/express/parsedUrl.test.js +0 -107
- package/lib/dataflow/sources/install/fastify/fastify.test.js +0 -207
- package/lib/dataflow/sources/install/fastify/index.test.js +0 -33
- package/lib/dataflow/sources/install/formidable1.test.js +0 -119
- package/lib/dataflow/sources/install/graphql-http.test.js +0 -133
- package/lib/dataflow/sources/install/hapi/hapi.test.js +0 -171
- package/lib/dataflow/sources/install/hapi/index.test.js +0 -33
- package/lib/dataflow/sources/install/http.test.js +0 -149
- package/lib/dataflow/sources/install/koa/index.test.js +0 -40
- package/lib/dataflow/sources/install/koa/koa-bodyparsers.test.js +0 -160
- package/lib/dataflow/sources/install/koa/koa-multer.test.js +0 -197
- package/lib/dataflow/sources/install/koa/koa-routers.test.js +0 -146
- package/lib/dataflow/sources/install/koa/koa2.test.js +0 -145
- package/lib/dataflow/sources/install/multer1.test.js +0 -143
- package/lib/dataflow/sources/install/qs6.test.js +0 -131
- package/lib/dataflow/sources/install/querystring.test.js +0 -82
- package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.test.js +0 -86
- package/lib/dataflow/sources/install/restify/index.test.js +0 -38
- package/lib/dataflow/sources/install/restify/jsonBodyParser.test.js +0 -140
- package/lib/dataflow/sources/install/restify/router.test.js +0 -81
- package/lib/dataflow/tag-utils-complete.test.js +0 -27
- package/lib/dataflow/tag-utils.test.js +0 -192
- package/lib/dataflow/tracker.test.js +0 -216
- package/lib/dataflow/utils/is-safe-content-type.test.js +0 -16
- package/lib/dataflow/utils/is-vulnerable.test.js +0 -115
- package/lib/event-factory.test.js +0 -326
- package/lib/get-policy.test.js +0 -194
- package/lib/get-source-context.test.js +0 -161
- package/lib/index.test.js +0 -45
- package/lib/make-source-context.test.js +0 -50
- package/lib/response-scanning/handlers/index.test.js +0 -419
- package/lib/response-scanning/handlers/utils.test.js +0 -380
- package/lib/response-scanning/index.test.js +0 -41
- package/lib/response-scanning/install/http.test.js +0 -175
- package/lib/rule-scopes.test.js +0 -27
- package/lib/sampler/common.test.js +0 -101
- package/lib/sampler/index.test.js +0 -313
- package/lib/session-configuration/handlers.test.js +0 -84
- package/lib/session-configuration/index.test.js +0 -36
- package/lib/session-configuration/install/express-session.test.js +0 -218
- package/lib/session-configuration/install/fastify-cookie.test.js +0 -63
- package/lib/session-configuration/install/hapi.test.js +0 -269
- package/lib/session-configuration/install/koa.test.js +0 -92
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { devNull } = require('node:os');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const { EventEmitter } = require('events');
|
|
6
|
-
const mocks = require('@contrast/test/mocks');
|
|
7
|
-
const { RouteAnalysisMonitor } = require('./common');
|
|
8
|
-
const frameworkData = require('@contrast/test/data/framework-routing-data')();
|
|
9
|
-
|
|
10
|
-
describe('assess sampler classes', function() {
|
|
11
|
-
describe('RouteAnalysisMonitor', function() {
|
|
12
|
-
it('getAnalysisInfo returns null when no discovery data was registered', function() {
|
|
13
|
-
const monitor = new RouteAnalysisMonitor(initMockCore());
|
|
14
|
-
[
|
|
15
|
-
['/user/1', '/user/2', '/user/3', '/user/4'],
|
|
16
|
-
['/user/1/cart', '/user/2/cart', '/user/3/cart', '/user/4/cart'],
|
|
17
|
-
['/products/all', '/products/all'],
|
|
18
|
-
['/products/1', '/products/2', '/products/3', '/products/4'],
|
|
19
|
-
].forEach((uriPaths) => {
|
|
20
|
-
for (const uriPath of uriPaths) {
|
|
21
|
-
expect(monitor.getAnalysisInfo({ uriPath })).to.deep.equal({ paused: false });
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
for (const [framework, testData] of Object.entries(frameworkData)) {
|
|
27
|
-
describe(`${framework} framework route monitoring`, function() {
|
|
28
|
-
let core, monitor;
|
|
29
|
-
|
|
30
|
-
before(function() {
|
|
31
|
-
core = initMockCore();
|
|
32
|
-
core.config.setValue('assess.probabilistic_sampling.route_monitor.ttl_ms', 500, 'CONFIGURATION_FILE');
|
|
33
|
-
monitor = new RouteAnalysisMonitor(core);
|
|
34
|
-
testData.forEach((d) => {
|
|
35
|
-
core.routeCoverage._normalizedUrlMapper.handleDiscover(d.routeInfo);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
testData.forEach(({ paths, routeInfo, skip, hasMapping }) => {
|
|
40
|
-
it(`${skip ? 'does not monitor' : 'monitors'} for normalizedUrl '${routeInfo.normalizedUrl}'`, async function() {
|
|
41
|
-
const groups = { paused: [], notPaused: [] };
|
|
42
|
-
let calls = 0;
|
|
43
|
-
|
|
44
|
-
// iterate at least twice if paths array has 1 element
|
|
45
|
-
[...paths, ...paths].forEach((uriPath, i) => {
|
|
46
|
-
const result = monitor.getAnalysisInfo({ uriPath, method: routeInfo.method });
|
|
47
|
-
calls++;
|
|
48
|
-
// update bucket
|
|
49
|
-
groups[result.paused ? 'paused' : 'notPaused'].push({ index: i, uriPath, ...result });
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (hasMapping !== false) {
|
|
53
|
-
// first call was unpaused
|
|
54
|
-
expect(groups.notPaused).to.have.lengthOf(1);
|
|
55
|
-
expect(groups.notPaused[0]).to.have.property('index', 0);
|
|
56
|
-
// all other calls were paused
|
|
57
|
-
expect(groups.paused).to.have.lengthOf(calls - 1);
|
|
58
|
-
for (const result of groups.paused) {
|
|
59
|
-
expect(result.index).to.be.greaterThan(0);
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
expect(groups.paused).to.have.lengthOf(0);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
function initMockCore() {
|
|
72
|
-
const { CONTRAST_CONFIG_PATH } = process.env;
|
|
73
|
-
process.env.CONTRAST_CONFIG_PATH = devNull;
|
|
74
|
-
|
|
75
|
-
let core;
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
core = {
|
|
79
|
-
// sampler needs this namespace to exist
|
|
80
|
-
assess: {},
|
|
81
|
-
// mocks
|
|
82
|
-
messages: new EventEmitter(),
|
|
83
|
-
logger: mocks.logger()
|
|
84
|
-
};
|
|
85
|
-
// use actual config so we can get dynamic effective values with TS message
|
|
86
|
-
// updates (mock doesn't). we can also test new effective config mappings.
|
|
87
|
-
require('@contrast/config')(core);
|
|
88
|
-
require('@contrast/route-coverage')(core);
|
|
89
|
-
core.config.setValue('assess.enable', true, 'CONTRAST_UI');
|
|
90
|
-
} catch (err) {
|
|
91
|
-
process.env.CONTRAST_CONFIG_PATH = CONTRAST_CONFIG_PATH;
|
|
92
|
-
|
|
93
|
-
console.dir(err);
|
|
94
|
-
throw err;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// reset to orig value
|
|
98
|
-
process.env.CONTRAST_CONFIG_PATH = CONTRAST_CONFIG_PATH;
|
|
99
|
-
|
|
100
|
-
return core;
|
|
101
|
-
}
|
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { EventEmitter } = require('events');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const { Event } = require('@contrast/common');
|
|
6
|
-
const mocks = require('@contrast/test/mocks');
|
|
7
|
-
const { devNull } = require('node:os');
|
|
8
|
-
|
|
9
|
-
const initSampler = require('.');
|
|
10
|
-
const { SamplingStrategies: { AssessTurnedOff, Probabilistic } } = require('./common');
|
|
11
|
-
|
|
12
|
-
const TRIALS = 1000;
|
|
13
|
-
const ZSCORE = 3.891; // 99.99% confidence
|
|
14
|
-
|
|
15
|
-
describe('assess sampler', function() {
|
|
16
|
-
it('sampling is disabled by default and assess.sampler is null', function() {
|
|
17
|
-
const core = initMockCore();
|
|
18
|
-
initSampler(core);
|
|
19
|
-
expect(core.assess.sampler).to.be.null;
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('samples at default rate of 0.10', function() {
|
|
23
|
-
const core = initMockCore();
|
|
24
|
-
core.config.setValue('assess.enable', true, 'CONTRAST_UI');
|
|
25
|
-
core.config.setValue('assess.probabilistic_sampling.enable', true, 'CONTRAST_UI');
|
|
26
|
-
// initialize after configs are set
|
|
27
|
-
const sampler = initSampler(core);
|
|
28
|
-
|
|
29
|
-
// verify configs set in before setup
|
|
30
|
-
expect(sampler).to.have.property('strategy', Probabilistic);
|
|
31
|
-
expect(sampler.opts).to.have.property('base_probability', 0.10);
|
|
32
|
-
expect(sampler).to.have.property('getSampleInfo').to.be.a('function');
|
|
33
|
-
// test behavior
|
|
34
|
-
testProbabilisticSampler(sampler);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('samples at p=base_probability', function() {
|
|
38
|
-
const core = initMockCore();
|
|
39
|
-
core.config.setValue('assess.probabilistic_sampling.enable', true, 'CONTRAST_UI');
|
|
40
|
-
core.config.setValue('assess.probabilistic_sampling.base_probability', 0.25, 'CONTRAST_UI');
|
|
41
|
-
// initialize after configs are set
|
|
42
|
-
const sampler = initSampler(core);
|
|
43
|
-
|
|
44
|
-
// verify configs
|
|
45
|
-
expect(sampler).to.have.property('strategy', Probabilistic);
|
|
46
|
-
expect(sampler.opts).to.have.property('base_probability', 0.25);
|
|
47
|
-
expect(sampler).to.have.property('getSampleInfo').to.be.a('function');
|
|
48
|
-
// test behavior
|
|
49
|
-
testProbabilisticSampler(sampler);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('probability is dynamic and set by TS server setting: assess.sampling.request_frequency', function() {
|
|
53
|
-
const core = initMockCore();
|
|
54
|
-
core.config.setValue('assess.probabilistic_sampling.enable', true, 'CONTRAST_UI');
|
|
55
|
-
core.config.setValue('assess.probabilistic_sampling.base_probability', 0.25, 'CONTRAST_UI');
|
|
56
|
-
// initialize after configs are set
|
|
57
|
-
initSampler(core);
|
|
58
|
-
// don't destructure to just { sampler } since the value of assess.sampler changes on update.
|
|
59
|
-
const { assess } = core;
|
|
60
|
-
|
|
61
|
-
// verify configs
|
|
62
|
-
expect(assess.sampler).to.have.property('strategy', Probabilistic);
|
|
63
|
-
expect(assess.sampler.opts).to.have.property('base_probability', 0.25);
|
|
64
|
-
expect(assess.sampler).to.have.property('getSampleInfo').to.be.a('function');
|
|
65
|
-
// test behavior
|
|
66
|
-
testProbabilisticSampler(assess.sampler);
|
|
67
|
-
|
|
68
|
-
// update
|
|
69
|
-
core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
|
|
70
|
-
assess: {
|
|
71
|
-
sampling: {
|
|
72
|
-
enable: true,
|
|
73
|
-
request_frequency: 2, // 1 / 2 = 0.50 base_probability
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// verify sampler was updated
|
|
79
|
-
expect(assess.sampler.opts.base_probability).to.equal(0.50);
|
|
80
|
-
// test behavior
|
|
81
|
-
testProbabilisticSampler(assess.sampler);
|
|
82
|
-
|
|
83
|
-
// test logging throughout init/updates
|
|
84
|
-
expect(core.logger.info.getCalls().map(c => c.args)).to.deep.equal([
|
|
85
|
-
// when initialized
|
|
86
|
-
[
|
|
87
|
-
{ strategy: Probabilistic, opts: { base_probability: 0.25, route_monitor: { enable: true, ttl_ms: 1800000 } } },
|
|
88
|
-
'updating assess sampler'
|
|
89
|
-
],
|
|
90
|
-
// update 1
|
|
91
|
-
[
|
|
92
|
-
{ strategy: Probabilistic, opts: { base_probability: 0.5, route_monitor: { enable: true, ttl_ms: 1800000 } } },
|
|
93
|
-
'updating assess sampler'
|
|
94
|
-
]
|
|
95
|
-
]);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('sampler always returns `canSample: false` if TS `assess.enable` setting is false', function() {
|
|
99
|
-
const core = initMockCore();
|
|
100
|
-
core.config.setValue('assess.enable', true, 'CONTRAST_UI');
|
|
101
|
-
core.config.setValue('assess.probabilistic_sampling.enable', true, 'CONTRAST_UI');
|
|
102
|
-
core.config.setValue('assess.probabilistic_sampling.base_probability', 0.50, 'CONTRAST_UI');
|
|
103
|
-
// initializes after configs are set
|
|
104
|
-
initSampler(core);
|
|
105
|
-
// don't destructure to just { sampler } since the value of assess.sampler changes on update.
|
|
106
|
-
const { assess } = core;
|
|
107
|
-
|
|
108
|
-
// verify configs set in before setup
|
|
109
|
-
expect(assess.sampler).to.have.property('strategy', Probabilistic);
|
|
110
|
-
expect(assess.sampler.opts).to.have.property('base_probability', 0.50);
|
|
111
|
-
expect(assess.sampler).to.have.property('getSampleInfo').to.be.a('function');
|
|
112
|
-
// test behavior
|
|
113
|
-
testProbabilisticSampler(assess.sampler);
|
|
114
|
-
|
|
115
|
-
// runtime update that says to disable assess
|
|
116
|
-
core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
|
|
117
|
-
assess: { enable: false }
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// verify updated sampling strategy
|
|
121
|
-
expect(assess.sampler.strategy).to.equal(AssessTurnedOff);
|
|
122
|
-
// test behavior
|
|
123
|
-
testDisabledSampler(assess.sampler);
|
|
124
|
-
|
|
125
|
-
// test logging throughout init/updates
|
|
126
|
-
expect(core.logger.info.getCalls().map(c => c.args)).to.deep.equal([
|
|
127
|
-
// when initialized
|
|
128
|
-
[
|
|
129
|
-
{ strategy: Probabilistic, opts: { base_probability: 0.5, route_monitor: { enable: true, ttl_ms: 1800000 } } },
|
|
130
|
-
'updating assess sampler'
|
|
131
|
-
],
|
|
132
|
-
// update 1
|
|
133
|
-
[
|
|
134
|
-
{ strategy: AssessTurnedOff, opts: undefined },
|
|
135
|
-
'updating assess sampler'
|
|
136
|
-
]
|
|
137
|
-
]);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('sampler behavior adjusts to series of TS updates', function() {
|
|
141
|
-
// setup
|
|
142
|
-
const cfgPath = process.env.CONTRAST_CONFIG_PATH;
|
|
143
|
-
process.env.CONTRAST_CONFIG_PATH = devNull;
|
|
144
|
-
const core = initMockCore();
|
|
145
|
-
process.env.CONTRAST_CONFIG_PATH = cfgPath;
|
|
146
|
-
|
|
147
|
-
core.config.setValue('assess.enable', true, 'CONTRAST_UI');
|
|
148
|
-
// core.config.setValue('assess.probabilistic_sampling.enable', true, 'DEFAULT_VALUE');
|
|
149
|
-
core.config.setValue('assess.probabilistic_sampling.base_probability', 0.50, 'CONTRAST_UI');
|
|
150
|
-
|
|
151
|
-
// initializes after configs are set
|
|
152
|
-
initSampler(core);
|
|
153
|
-
|
|
154
|
-
// don't destructure to just { sampler } since the value of assess.sampler changes on update
|
|
155
|
-
const { assess } = core;
|
|
156
|
-
|
|
157
|
-
// disabled by config
|
|
158
|
-
expect(assess.sampler).to.be.null;
|
|
159
|
-
|
|
160
|
-
// set to PRODUCTION to enable sampling
|
|
161
|
-
core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
|
|
162
|
-
environment: 'PRODUCTION',
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// verify sampler was updated
|
|
166
|
-
expect(assess.sampler.opts.base_probability).to.equal(0.50);
|
|
167
|
-
// test behavior
|
|
168
|
-
testProbabilisticSampler(assess.sampler);
|
|
169
|
-
|
|
170
|
-
// disable sampling by setting to DEVELOPMENT
|
|
171
|
-
core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
|
|
172
|
-
environment: 'DEVELOPMENT',
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// since assess.probabilistic_sampling is off and env is no longer PRODUCTION
|
|
176
|
-
expect(assess.sampler).to.be.null;
|
|
177
|
-
|
|
178
|
-
// disable Assess
|
|
179
|
-
core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
|
|
180
|
-
assess: { enable: false },
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// verify updated sampling strategy
|
|
184
|
-
expect(assess.sampler.strategy).to.equal(AssessTurnedOff);
|
|
185
|
-
// test behavior
|
|
186
|
-
testDisabledSampler(assess.sampler);
|
|
187
|
-
|
|
188
|
-
// re-enable Assess and set new probability via request_frequency
|
|
189
|
-
core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
|
|
190
|
-
assess: {
|
|
191
|
-
enable: true,
|
|
192
|
-
sampling: {
|
|
193
|
-
enable: true,
|
|
194
|
-
request_frequency: 50, //
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// verify sampler was updated
|
|
200
|
-
expect(assess.sampler.opts.base_probability).to.equal(1 / 50);
|
|
201
|
-
// test behavior
|
|
202
|
-
testProbabilisticSampler(assess.sampler);
|
|
203
|
-
|
|
204
|
-
// test logging throughout init/updates
|
|
205
|
-
expect(core.logger.info.getCalls().map(c => c.args)).to.deep.equal([
|
|
206
|
-
// update 1: env=PRODUCTION enables sampling
|
|
207
|
-
[
|
|
208
|
-
{ strategy: Probabilistic, opts: { base_probability: 0.5, route_monitor: { enable: true, ttl_ms: 1800000 } } },
|
|
209
|
-
'updating assess sampler'
|
|
210
|
-
],
|
|
211
|
-
// update 2: env = DEVELOPMENT disables sampling
|
|
212
|
-
['assess sampling disabled'],
|
|
213
|
-
// update 3: assess.enable=false sets disabled sampling strategy
|
|
214
|
-
[
|
|
215
|
-
{ strategy: AssessTurnedOff, opts: undefined },
|
|
216
|
-
'updating assess sampler'
|
|
217
|
-
],
|
|
218
|
-
// update 5: assess.enable=true and request_frequency=50 re-enables assess and new sampling probability
|
|
219
|
-
[
|
|
220
|
-
{ strategy: Probabilistic, opts: { base_probability: 0.02, route_monitor: { enable: true, ttl_ms: 1800000 } } },
|
|
221
|
-
'updating assess sampler'
|
|
222
|
-
]
|
|
223
|
-
]);
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
function initMockCore() {
|
|
228
|
-
const { CONTRAST_CONFIG_PATH } = process.env;
|
|
229
|
-
process.env.CONTRAST_CONFIG_PATH = devNull;
|
|
230
|
-
|
|
231
|
-
let core;
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
core = {
|
|
235
|
-
// sampler needs this namespace to exist
|
|
236
|
-
assess: {},
|
|
237
|
-
// mocks
|
|
238
|
-
messages: new EventEmitter(),
|
|
239
|
-
logger: mocks.logger()
|
|
240
|
-
};
|
|
241
|
-
// use actual config so we can get dynamic effective values with TS message
|
|
242
|
-
// updates (mock doesn't). we can also test new effective config mappings.
|
|
243
|
-
require('@contrast/config')(core);
|
|
244
|
-
require('@contrast/route-coverage')(core);
|
|
245
|
-
|
|
246
|
-
core.config.setValue('assess.enable', true, 'CONTRAST_UI');
|
|
247
|
-
} catch (err) {
|
|
248
|
-
process.env.CONTRAST_CONFIG_PATH = CONTRAST_CONFIG_PATH;
|
|
249
|
-
|
|
250
|
-
console.dir(err);
|
|
251
|
-
throw err;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// reset to orig value
|
|
255
|
-
process.env.CONTRAST_CONFIG_PATH = CONTRAST_CONFIG_PATH;
|
|
256
|
-
|
|
257
|
-
return core;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// https://en.wikipedia.org/wiki/Binomial_distribution
|
|
261
|
-
function getStats(p) {
|
|
262
|
-
const mean = TRIALS * p;
|
|
263
|
-
const variance = mean * (1 - p);
|
|
264
|
-
const standardDev = Math.sqrt(variance);
|
|
265
|
-
const marginOfError = ZSCORE * standardDev;
|
|
266
|
-
const confidenceInterval = [
|
|
267
|
-
Math.max(0, mean - marginOfError),
|
|
268
|
-
mean + marginOfError
|
|
269
|
-
];
|
|
270
|
-
|
|
271
|
-
return {
|
|
272
|
-
p,
|
|
273
|
-
mean,
|
|
274
|
-
variance,
|
|
275
|
-
standardDev,
|
|
276
|
-
confidenceInterval,
|
|
277
|
-
trials: TRIALS,
|
|
278
|
-
zscore: ZSCORE,
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function testProbabilisticSampler(sampler) {
|
|
283
|
-
const { opts } = sampler;
|
|
284
|
-
const store = {
|
|
285
|
-
assess: {
|
|
286
|
-
reqData: { uriPath: '/foo' }
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// run trials and count how many times sampler says okay to analyze
|
|
291
|
-
let observedSampleCount = 0;
|
|
292
|
-
for (let n = 0; n < TRIALS; n++) {
|
|
293
|
-
const info = sampler.getSampleInfo({ store });
|
|
294
|
-
if (info.canSample) observedSampleCount++;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const stats = getStats(opts.base_probability);
|
|
298
|
-
const { confidenceInterval: [low, high] } = stats;
|
|
299
|
-
|
|
300
|
-
// for debugging/visibility
|
|
301
|
-
// console.log({ observedSampleCount, ...stats })
|
|
302
|
-
expect(observedSampleCount).to.be.greaterThan(low).and.lessThan(high);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
function testDisabledSampler(sampler) {
|
|
306
|
-
// run trials and count how many times sampler says okay to analyze
|
|
307
|
-
let observedSampleCount = 0;
|
|
308
|
-
for (let n = 0; n < TRIALS; n++) {
|
|
309
|
-
const info = sampler.getSampleInfo();
|
|
310
|
-
if (info.canSample) observedSampleCount++;
|
|
311
|
-
}
|
|
312
|
-
expect(observedSampleCount).to.equal(0);
|
|
313
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { expect } = require('chai');
|
|
4
|
-
const sinon = require('sinon');
|
|
5
|
-
const { initAssessFixture } = require('@contrast/test/fixtures');
|
|
6
|
-
const handlers = require('./handlers');
|
|
7
|
-
const {
|
|
8
|
-
Event,
|
|
9
|
-
SessionConfigurationRule: {
|
|
10
|
-
HTTPONLY,
|
|
11
|
-
SECURE_FLAG_MISSING,
|
|
12
|
-
}
|
|
13
|
-
} = require('@contrast/common');
|
|
14
|
-
|
|
15
|
-
describe('assess session-configuration handlers', function () {
|
|
16
|
-
let sessionConfiguration, core, simulateRequestScope;
|
|
17
|
-
|
|
18
|
-
beforeEach(function () {
|
|
19
|
-
({ core, simulateRequestScope } = initAssessFixture());
|
|
20
|
-
sessionConfiguration = handlers(core);
|
|
21
|
-
sinon.spy(core.messages, 'emit');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
[
|
|
25
|
-
{
|
|
26
|
-
method: 'handleHttpOnly',
|
|
27
|
-
cookie: 'HttpOnly',
|
|
28
|
-
ruleId: HTTPONLY
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
method: 'handleSecure',
|
|
32
|
-
cookie: 'Secure',
|
|
33
|
-
ruleId: SECURE_FLAG_MISSING
|
|
34
|
-
}
|
|
35
|
-
].forEach(function ({ method, cookie, ruleId }) {
|
|
36
|
-
it(`should not report findings if cookie includes ${cookie} - ${method}`, function () {
|
|
37
|
-
simulateRequestScope(() => {
|
|
38
|
-
const sourceContext = core.assess.getSourceContext();
|
|
39
|
-
sessionConfiguration[method](sourceContext, `foo; cookie; ${cookie};`);
|
|
40
|
-
expect(core.messages.emit).to.not.have.been.called;
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it(`should report when ${cookie} is not part of the cookie - ${method}`, function () {
|
|
45
|
-
simulateRequestScope(() => {
|
|
46
|
-
const sourceContext = core.assess.getSourceContext();
|
|
47
|
-
const sessionEvent = { mock: 'sessionEvent' };
|
|
48
|
-
|
|
49
|
-
sessionConfiguration[method](sourceContext, 'foo; cookie', sessionEvent);
|
|
50
|
-
expect(core.messages.emit).to.have.been.calledWith(Event.ASSESS_SESSION_CONFIGURATION_FINDING, {
|
|
51
|
-
ruleId,
|
|
52
|
-
sinkEvent: sessionEvent,
|
|
53
|
-
properties: {
|
|
54
|
-
evidence: 'foo; cookie'
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it(`should report when ${cookie} (an array) is not part of the cookie - ${method} `, function () {
|
|
61
|
-
simulateRequestScope(() => {
|
|
62
|
-
const sourceContext = core.assess.getSourceContext();
|
|
63
|
-
const sessionEvent = { mock: 'sessionEvent' };
|
|
64
|
-
|
|
65
|
-
sessionConfiguration[method](sourceContext, ['foo; cookie', 'hello; cookie3'], sessionEvent);
|
|
66
|
-
expect(core.messages.emit).to.have.been.calledWith(Event.ASSESS_SESSION_CONFIGURATION_FINDING, {
|
|
67
|
-
ruleId,
|
|
68
|
-
sinkEvent: sessionEvent,
|
|
69
|
-
properties: {
|
|
70
|
-
evidence: 'foo; cookie'
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(core.messages.emit).not.to.have.been.calledWith(Event.ASSESS_SESSION_CONFIGURATION_FINDING, {
|
|
75
|
-
ruleId,
|
|
76
|
-
sinkEvent: sessionEvent,
|
|
77
|
-
properties: {
|
|
78
|
-
evidence: 'hello; cookie3'
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { expect } = require('chai');
|
|
4
|
-
const proxyquire = require('proxyquire');
|
|
5
|
-
const mocks = require('@contrast/test/mocks');
|
|
6
|
-
|
|
7
|
-
const moduleMock = (moduleName, mock) => (core) => {
|
|
8
|
-
core.assess.sessionConfiguration[moduleName] = mock[moduleName];
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
describe('assess session-configuration', function () {
|
|
12
|
-
let core, sessionConfigurationMock, sessionConfigurationModule, modulesWithInstall;
|
|
13
|
-
|
|
14
|
-
beforeEach(function () {
|
|
15
|
-
core = mocks.core();
|
|
16
|
-
core.scopes = mocks.scopes();
|
|
17
|
-
core.assess = mocks.assess();
|
|
18
|
-
sessionConfigurationMock = core.assess.sessionConfiguration;
|
|
19
|
-
sessionConfigurationModule = proxyquire('.', {
|
|
20
|
-
'./install/express-session': moduleMock('expressSession', sessionConfigurationMock),
|
|
21
|
-
'./install/hapi': moduleMock('hapiSession', sessionConfigurationMock),
|
|
22
|
-
'./install/fastify-cookie': moduleMock('fastifyCookie', sessionConfigurationMock),
|
|
23
|
-
'./install/koa': moduleMock('koaSession', sessionConfigurationMock),
|
|
24
|
-
});
|
|
25
|
-
modulesWithInstall = ['expressSession', 'hapiSession', 'fastifyCookie', 'koaSession'];
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('installs the components', function () {
|
|
29
|
-
sessionConfigurationModule(core).install();
|
|
30
|
-
|
|
31
|
-
modulesWithInstall.forEach((module) => {
|
|
32
|
-
expect(core.assess.sessionConfiguration[module].install).to.have.been.calledOnce;
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|