@contrast/protect 1.54.0 → 1.54.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/error-handlers/common-handler.test.js +0 -52
- package/lib/error-handlers/index.test.js +0 -32
- package/lib/error-handlers/init-domain.test.js +0 -22
- package/lib/error-handlers/install/express.test.js +0 -290
- package/lib/error-handlers/install/fastify.test.js +0 -130
- package/lib/error-handlers/install/hapi.test.js +0 -102
- package/lib/error-handlers/install/koa2.test.js +0 -83
- package/lib/error-handlers/install/restify.test.js +0 -57
- package/lib/get-source-context.test.js +0 -35
- package/lib/hardening/handlers.test.js +0 -89
- package/lib/hardening/index.test.js +0 -31
- package/lib/hardening/install/node-serialize0.test.js +0 -58
- package/lib/index.test.js +0 -53
- package/lib/input-analysis/handlers.test.js +0 -1604
- package/lib/input-analysis/index.test.js +0 -45
- package/lib/input-analysis/install/body-parser1.test.js +0 -134
- package/lib/input-analysis/install/busboy1.test.js +0 -81
- package/lib/input-analysis/install/cookie-parser1.test.js +0 -144
- package/lib/input-analysis/install/express.test.js +0 -241
- package/lib/input-analysis/install/fastify.test.js +0 -96
- package/lib/input-analysis/install/formidable1.test.js +0 -114
- package/lib/input-analysis/install/hapi.test.js +0 -292
- package/lib/input-analysis/install/http.test.js +0 -270
- package/lib/input-analysis/install/koa-body5.test.js +0 -92
- package/lib/input-analysis/install/koa-bodyparser4.test.js +0 -92
- package/lib/input-analysis/install/koa2.test.js +0 -259
- package/lib/input-analysis/install/multer1.test.js +0 -209
- package/lib/input-analysis/install/qs6.test.js +0 -79
- package/lib/input-analysis/install/restify.test.js +0 -98
- package/lib/input-analysis/install/universal-cookie4.test.js +0 -70
- package/lib/input-analysis/ip-analysis.test.js +0 -71
- package/lib/input-analysis/virtual-patches.test.js +0 -106
- package/lib/input-tracing/handlers/index.test.js +0 -1237
- package/lib/input-tracing/index.test.js +0 -62
- package/lib/input-tracing/install/child-process.test.js +0 -133
- package/lib/input-tracing/install/eval.test.js +0 -78
- package/lib/input-tracing/install/fs.test.js +0 -108
- package/lib/input-tracing/install/function.test.js +0 -81
- package/lib/input-tracing/install/http.test.js +0 -85
- package/lib/input-tracing/install/http2.test.js +0 -83
- package/lib/input-tracing/install/marsdb.test.js +0 -126
- package/lib/input-tracing/install/mongodb.test.js +0 -280
- package/lib/input-tracing/install/mssql.test.js +0 -81
- package/lib/input-tracing/install/mysql.test.js +0 -108
- package/lib/input-tracing/install/postgres.test.js +0 -117
- package/lib/input-tracing/install/sequelize.test.js +0 -78
- package/lib/input-tracing/install/spdy.test.js +0 -76
- package/lib/input-tracing/install/sqlite3.test.js +0 -88
- package/lib/input-tracing/install/vm.test.js +0 -176
- package/lib/make-response-blocker.test.js +0 -99
- package/lib/make-source-context.test.js +0 -219
- package/lib/policy.test.js +0 -446
- package/lib/semantic-analysis/handlers.test.js +0 -379
- package/lib/semantic-analysis/index.test.js +0 -38
- package/lib/semantic-analysis/install/libxmljs.test.js +0 -156
- package/lib/semantic-analysis/utils/xml-analysis.test.js +0 -156
- package/lib/throw-security-exception.test.js +0 -37
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { expect } = require('chai');
|
|
4
|
-
const sinon = require('sinon');
|
|
5
|
-
const proxyquire = require('proxyquire');
|
|
6
|
-
|
|
7
|
-
const MODULES = [
|
|
8
|
-
'childProcess',
|
|
9
|
-
'eval',
|
|
10
|
-
'fs',
|
|
11
|
-
'function',
|
|
12
|
-
'http',
|
|
13
|
-
'http2',
|
|
14
|
-
'marsdb',
|
|
15
|
-
'mongodb',
|
|
16
|
-
'mssql',
|
|
17
|
-
'mysql',
|
|
18
|
-
'postgres',
|
|
19
|
-
'sequelize',
|
|
20
|
-
'spdy',
|
|
21
|
-
'sqlite3',
|
|
22
|
-
'vm',
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
describe('protect input-tracing', function () {
|
|
26
|
-
let core, inputTracing;
|
|
27
|
-
|
|
28
|
-
beforeEach(function () {
|
|
29
|
-
core = {};
|
|
30
|
-
core.protect = {};
|
|
31
|
-
|
|
32
|
-
const hooksMock = (hookProp) => (core) => {
|
|
33
|
-
core.protect.inputTracing[hookProp] = { install: sinon.stub() };
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
inputTracing = proxyquire('.', {
|
|
37
|
-
'./install/child-process': hooksMock('childProcess'),
|
|
38
|
-
'./install/eval': hooksMock('eval'),
|
|
39
|
-
'./install/fs': hooksMock('fs'),
|
|
40
|
-
'./install/function': hooksMock('function'),
|
|
41
|
-
'./install/http': hooksMock('http'),
|
|
42
|
-
'./install/http2': hooksMock('http2'),
|
|
43
|
-
'./install/marsdb': hooksMock('marsdb'),
|
|
44
|
-
'./install/mongodb': hooksMock('mongodb'),
|
|
45
|
-
'./install/mssql': hooksMock('mssql'),
|
|
46
|
-
'./install/mysql': hooksMock('mysql'),
|
|
47
|
-
'./install/postgres': hooksMock('postgres'),
|
|
48
|
-
'./install/sequelize': hooksMock('sequelize'),
|
|
49
|
-
'./install/spdy': hooksMock('spdy'),
|
|
50
|
-
'./install/sqlite3': hooksMock('sqlite3'),
|
|
51
|
-
'./install/vm': hooksMock('vm'),
|
|
52
|
-
})(core);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('calls the install() method of the required hooks', function () {
|
|
56
|
-
inputTracing.install();
|
|
57
|
-
|
|
58
|
-
MODULES.forEach((module) => {
|
|
59
|
-
expect(inputTracing[module].install).to.have.been.called;
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
});
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const sinon = require('sinon');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const patcher = require('@contrast/patcher');
|
|
6
|
-
const mocks = require('@contrast/test/mocks/');
|
|
7
|
-
|
|
8
|
-
describe('protect input-tracing child-process', function () {
|
|
9
|
-
const cpInstr = require('./child-process');
|
|
10
|
-
const store = { protect: {} };
|
|
11
|
-
let cp, origCp, core;
|
|
12
|
-
|
|
13
|
-
beforeEach(function () {
|
|
14
|
-
origCp = {
|
|
15
|
-
exec: sinon.stub(),
|
|
16
|
-
execSync: sinon.stub()
|
|
17
|
-
};
|
|
18
|
-
cp = {
|
|
19
|
-
exec: origCp.exec,
|
|
20
|
-
execSync: origCp.execSync
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
core = mocks.core();
|
|
24
|
-
core.logger = mocks.logger();
|
|
25
|
-
core.depHooks = mocks.depHooks();
|
|
26
|
-
core.depHooks.resolve.yields(cp);
|
|
27
|
-
core.scopes = mocks.scopes();
|
|
28
|
-
core.scopes.sources = {
|
|
29
|
-
getStore: sinon.stub().returns(store)
|
|
30
|
-
};
|
|
31
|
-
core.patcher = patcher(core);
|
|
32
|
-
core.protect = mocks.protect();
|
|
33
|
-
require('../../get-source-context')(core);
|
|
34
|
-
|
|
35
|
-
cpInstr(core);
|
|
36
|
-
|
|
37
|
-
core.protect.inputTracing.cpInstrumentation.install();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('handleCommandInjection() is called with expected values', function () {
|
|
41
|
-
const methodArgs = ['foo', 'bar'];
|
|
42
|
-
|
|
43
|
-
['exec', 'execSync'].forEach((method) => {
|
|
44
|
-
const name = `child_process.${method}`;
|
|
45
|
-
|
|
46
|
-
it(`${name}`, function () {
|
|
47
|
-
cp[method](...methodArgs);
|
|
48
|
-
|
|
49
|
-
const value = methodArgs[0];
|
|
50
|
-
|
|
51
|
-
expect(core.protect.inputTracing.handleCommandInjection).to.have.been.calledWith(
|
|
52
|
-
store.protect,
|
|
53
|
-
{ name, value, stacktraceOpts: { constructorOpt: cp[method], prependFrames: [sinon.match.func] } }
|
|
54
|
-
);
|
|
55
|
-
expect(core.protect.semanticAnalysis.handleCommandInjectionCommandBackdoors).to.have.been.calledWith(
|
|
56
|
-
store.protect,
|
|
57
|
-
{ name, value, stacktraceOpts: { constructorOpt: cp[method], prependFrames: [sinon.match.func] } }
|
|
58
|
-
);
|
|
59
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticChainedCommands).to.have.been.calledWith(
|
|
60
|
-
store.protect,
|
|
61
|
-
{ name, value, stacktraceOpts: { constructorOpt: cp[method], prependFrames: [sinon.match.func] } }
|
|
62
|
-
);
|
|
63
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticDangerous).to.have.been.calledWith(
|
|
64
|
-
store.protect,
|
|
65
|
-
{ name, value, stacktraceOpts: { constructorOpt: cp[method], prependFrames: [sinon.match.func] } }
|
|
66
|
-
);
|
|
67
|
-
expect(core.protect.semanticAnalysis.handlePathTraversalFileSecurityBypass).to.have.been.calledWith(
|
|
68
|
-
store.protect,
|
|
69
|
-
{ name, value, stacktraceOpts: { constructorOpt: cp[method], prependFrames: [sinon.match.func] } }
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('handleCommandInjection() is not called when method args are not relevant', function () {
|
|
76
|
-
const methodArgs = [1, undefined];
|
|
77
|
-
|
|
78
|
-
['exec', 'execSync'].forEach((method) => {
|
|
79
|
-
const name = `child_process.${method}`;
|
|
80
|
-
|
|
81
|
-
it(name, function () {
|
|
82
|
-
cp[method](...methodArgs);
|
|
83
|
-
|
|
84
|
-
expect(core.protect.inputTracing.handleCommandInjection).not.to.have.been.called;
|
|
85
|
-
expect(core.protect.semanticAnalysis.handleCommandInjectionCommandBackdoors).not.to.have.been.called;
|
|
86
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticChainedCommands).not.to.have.been.called;
|
|
87
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticDangerous).not.to.have.been.called;
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('handleCommandInjection() is not called when instrumentation is locked', function () {
|
|
93
|
-
const methodArgs = ['foo', 'bar'];
|
|
94
|
-
|
|
95
|
-
beforeEach(function () {
|
|
96
|
-
core.scopes.instrumentation.isLocked.returns(true);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
['exec', 'execSync'].forEach((method) => {
|
|
100
|
-
const name = `child_process.${method}`;
|
|
101
|
-
|
|
102
|
-
it(name, function () {
|
|
103
|
-
cp[method](...methodArgs);
|
|
104
|
-
|
|
105
|
-
expect(core.protect.inputTracing.handleCommandInjection).not.to.have.been.called;
|
|
106
|
-
expect(core.protect.semanticAnalysis.handleCommandInjectionCommandBackdoors).not.to.have.been.called;
|
|
107
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticChainedCommands).not.to.have.been.called;
|
|
108
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticDangerous).not.to.have.been.called;
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe('handleCommandInjection() is not called when there is no Protect sourceContext', function () {
|
|
114
|
-
const methodArgs = ['foo', 'bar'];
|
|
115
|
-
|
|
116
|
-
beforeEach(function () {
|
|
117
|
-
core.scopes.sources.getStore.returns({ protect: null });
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
['exec', 'execSync'].forEach((method) => {
|
|
121
|
-
const name = `child_process.${method}`;
|
|
122
|
-
|
|
123
|
-
it(name, function () {
|
|
124
|
-
cp[method](...methodArgs);
|
|
125
|
-
|
|
126
|
-
expect(core.protect.inputTracing.handleCommandInjection).not.to.have.been.called;
|
|
127
|
-
expect(core.protect.semanticAnalysis.handleCommandInjectionCommandBackdoors).not.to.have.been.called;
|
|
128
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticChainedCommands).not.to.have.been.called;
|
|
129
|
-
expect(core.protect.semanticAnalysis.handleCmdInjectionSemanticDangerous).not.to.have.been.called;
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const sinon = require('sinon');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const patcher = require('@contrast/patcher');
|
|
6
|
-
const mocks = require('@contrast/test/mocks');
|
|
7
|
-
|
|
8
|
-
describe('protect input-tracing eval', function () {
|
|
9
|
-
const evalInstr = require('./eval');
|
|
10
|
-
const store = { protect: {} };
|
|
11
|
-
let evalArg, core;
|
|
12
|
-
|
|
13
|
-
beforeEach(function () {
|
|
14
|
-
evalArg = 'function() { return "hi"; }';
|
|
15
|
-
|
|
16
|
-
if (!global.ContrastMethods) {
|
|
17
|
-
global.ContrastMethods = {};
|
|
18
|
-
}
|
|
19
|
-
global.ContrastMethods.eval = sinon.stub();
|
|
20
|
-
|
|
21
|
-
core = mocks.core();
|
|
22
|
-
core.logger = mocks.logger();
|
|
23
|
-
core.depHooks = mocks.depHooks();
|
|
24
|
-
core.depHooks.resolve.yields(global.ContrastMethods.eval);
|
|
25
|
-
core.scopes = mocks.scopes();
|
|
26
|
-
sinon.stub(core.scopes.sources, 'getStore').returns(store);
|
|
27
|
-
core.patcher = patcher(core);
|
|
28
|
-
core.protect = mocks.protect();
|
|
29
|
-
require('../../get-source-context')(core);
|
|
30
|
-
|
|
31
|
-
evalInstr(core);
|
|
32
|
-
|
|
33
|
-
core.protect.inputTracing.evalInstrumentation.install();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
afterEach(function () {
|
|
37
|
-
Reflect.deleteProperty(global.ContrastMethods);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('ssjsInjection() is called with expected values', function () {
|
|
41
|
-
global.ContrastMethods.eval(evalArg);
|
|
42
|
-
|
|
43
|
-
expect(core.protect.inputTracing.ssjsInjection).to.have.been.calledWith(
|
|
44
|
-
store.protect,
|
|
45
|
-
{ name: 'eval', value: evalArg, stacktraceOpts: { constructorOpt: sinon.match.func, prependFrames: [sinon.match.func] } }
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('ssjsInjection() is not called when method args are not relevant', function () {
|
|
50
|
-
global.ContrastMethods.eval(1, evalArg);
|
|
51
|
-
|
|
52
|
-
expect(core.protect.inputTracing.ssjsInjection).not.to.have.been.called;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('ssjsInjection() is not called when instrumentation is locked', function () {
|
|
56
|
-
core.scopes.instrumentation.isLocked.returns(true);
|
|
57
|
-
|
|
58
|
-
global.ContrastMethods.eval(evalArg);
|
|
59
|
-
|
|
60
|
-
expect(core.protect.inputTracing.ssjsInjection).not.to.have.been.called;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('ssjsInjection() is not called when there is no Protect sourceContext', function () {
|
|
64
|
-
core.scopes.sources.getStore.returns({ protect: null });
|
|
65
|
-
|
|
66
|
-
global.ContrastMethods.eval(evalArg);
|
|
67
|
-
|
|
68
|
-
expect(core.protect.inputTracing.ssjsInjection).not.to.have.been.called;
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('logs an error when there is no `global.ContrastMethods.eval` method', function () {
|
|
72
|
-
global.ContrastMethods.eval = null;
|
|
73
|
-
|
|
74
|
-
core.protect.inputTracing.evalInstrumentation.install();
|
|
75
|
-
|
|
76
|
-
expect(core.logger.error).to.have.been.calledOnceWith('Cannot install `eval` instrumentation - Contrast method DNE');
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const sinon = require('sinon');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const { FS_METHODS } = require('@contrast/common');
|
|
6
|
-
const patcher = require('@contrast/patcher');
|
|
7
|
-
const mocks = require('@contrast/test/mocks');
|
|
8
|
-
|
|
9
|
-
describe('protect input-tracing fs', function () {
|
|
10
|
-
const store = { protect: {} };
|
|
11
|
-
let fs, fsPromises, core;
|
|
12
|
-
|
|
13
|
-
beforeEach(function () {
|
|
14
|
-
fs = {
|
|
15
|
-
promises: {}
|
|
16
|
-
};
|
|
17
|
-
fsPromises = {};
|
|
18
|
-
|
|
19
|
-
for (const { name, promises, sync } of FS_METHODS) {
|
|
20
|
-
fs[name] = sinon.stub();
|
|
21
|
-
if (sync) {
|
|
22
|
-
fs[`${name}Sync`] = sinon.stub();
|
|
23
|
-
}
|
|
24
|
-
if (promises) {
|
|
25
|
-
fsPromises[name] = sinon.stub();
|
|
26
|
-
fs.promises[name] = sinon.stub();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
core = mocks.core();
|
|
31
|
-
core.logger = mocks.logger();
|
|
32
|
-
core.depHooks = mocks.depHooks();
|
|
33
|
-
core.depHooks.resolve.withArgs(sinon.match({ name: 'fs' })).yields(fs);
|
|
34
|
-
core.depHooks.resolve.withArgs(sinon.match({ name: 'fs/promises' })).yields(fsPromises);
|
|
35
|
-
core.scopes = mocks.scopes();
|
|
36
|
-
sinon.stub(core.scopes.sources, 'getStore').returns(store);
|
|
37
|
-
core.patcher = patcher(core);
|
|
38
|
-
core.protect = mocks.protect();
|
|
39
|
-
require('../../get-source-context')(core);
|
|
40
|
-
|
|
41
|
-
require('./fs')(core).install();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
for (const { name, promises, sync, indices } of FS_METHODS) {
|
|
45
|
-
const methodsUnderTest = [{ name: `fs.${name}`, getFn: () => fs[name] }];
|
|
46
|
-
if (sync) {
|
|
47
|
-
methodsUnderTest.push({ name: `fs.${name}Sync`, getFn: () => fs[`${name}Sync`] });
|
|
48
|
-
}
|
|
49
|
-
if (promises) {
|
|
50
|
-
methodsUnderTest.push({ name: `fsPromises.${name}`, getFn: () => fsPromises[name] });
|
|
51
|
-
methodsUnderTest.push({ name: `fs.promises.${name}`, getFn: () => fs.promises[name] });
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
for (const { name, getFn } of methodsUnderTest) {
|
|
55
|
-
describe(name, function () {
|
|
56
|
-
it('handlePathTraversal() is called with expected values', function () {
|
|
57
|
-
const method = getFn();
|
|
58
|
-
const methodArgs = ['foo', 'bar'];
|
|
59
|
-
method(...methodArgs);
|
|
60
|
-
|
|
61
|
-
for (const idx of indices) {
|
|
62
|
-
const value = methodArgs[idx];
|
|
63
|
-
|
|
64
|
-
expect(core.protect.inputTracing.handlePathTraversal).to.have.been.calledWith(
|
|
65
|
-
store.protect,
|
|
66
|
-
{
|
|
67
|
-
name,
|
|
68
|
-
value,
|
|
69
|
-
stacktraceOpts: {
|
|
70
|
-
constructorOpt: method,
|
|
71
|
-
prependFrames: [sinon.match.func]
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('handlePathTraversal() is not called when method args are not relevant', function () {
|
|
79
|
-
const method = getFn();
|
|
80
|
-
const methodArgs = [1, undefined];
|
|
81
|
-
method(...methodArgs);
|
|
82
|
-
|
|
83
|
-
expect(core.protect.inputTracing.handlePathTraversal).not.to.have.been.called;
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
it('handlePathTraversal() is not called when instrumentation is locked', function () {
|
|
88
|
-
const method = getFn();
|
|
89
|
-
const methodArgs = ['foo', 'bar'];
|
|
90
|
-
core.scopes.instrumentation.isLocked.returns(true);
|
|
91
|
-
method(...methodArgs);
|
|
92
|
-
|
|
93
|
-
expect(core.protect.inputTracing.handlePathTraversal).not.to.have.been.called;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
it('handlePathTraversal() is not called when there is no Protect sourceContext', function () {
|
|
98
|
-
const method = getFn();
|
|
99
|
-
const methodArgs = ['foo', 'bar'];
|
|
100
|
-
core.scopes.sources.getStore.returns({ protect: null });
|
|
101
|
-
method(...methodArgs);
|
|
102
|
-
|
|
103
|
-
expect(core.protect.inputTracing.handlePathTraversal).not.to.have.been.called;
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
});
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const sinon = require('sinon');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const patcher = require('@contrast/patcher');
|
|
6
|
-
const mocks = require('@contrast/test/mocks');
|
|
7
|
-
|
|
8
|
-
describe('protect input-tracing function', function () {
|
|
9
|
-
const functionInstr = require('./function');
|
|
10
|
-
const store = { protect: {} };
|
|
11
|
-
let constructorArg, core;
|
|
12
|
-
|
|
13
|
-
beforeEach(function () {
|
|
14
|
-
constructorArg = 'return "hi";';
|
|
15
|
-
|
|
16
|
-
if (!global.ContrastMethods) {
|
|
17
|
-
global.ContrastMethods = {};
|
|
18
|
-
}
|
|
19
|
-
global.ContrastMethods.Function = sinon.stub();
|
|
20
|
-
|
|
21
|
-
core = mocks.core();
|
|
22
|
-
core.logger = mocks.logger();
|
|
23
|
-
core.depHooks = mocks.depHooks();
|
|
24
|
-
core.depHooks.resolve.yields(global.ContrastMethods.Function);
|
|
25
|
-
core.scopes = mocks.scopes();
|
|
26
|
-
sinon.stub(core.scopes.sources, 'getStore').returns(store);
|
|
27
|
-
core.patcher = patcher(core);
|
|
28
|
-
core.protect = mocks.protect();
|
|
29
|
-
require('../../get-source-context')(core);
|
|
30
|
-
|
|
31
|
-
functionInstr(core);
|
|
32
|
-
|
|
33
|
-
core.protect.inputTracing.functionInstrumentation.install();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
afterEach(function () {
|
|
37
|
-
Reflect.deleteProperty(global.ContrastMethods);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('ssjsInjection() is called with expected values', function () {
|
|
41
|
-
global.ContrastMethods.Function(constructorArg);
|
|
42
|
-
|
|
43
|
-
expect(core.protect.inputTracing.ssjsInjection).to.have.been.calledWith(
|
|
44
|
-
store.protect,
|
|
45
|
-
{ name: 'Function', value: constructorArg, stacktraceOpts: { constructorOpt: sinon.match.func, prependFrames: [sinon.match.func] } }
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('ssjsInjection() is called only with the value for the function body', function () {
|
|
50
|
-
global.ContrastMethods.Function('a', 'return a');
|
|
51
|
-
|
|
52
|
-
expect(core.protect.inputTracing.ssjsInjection).to.have.been.calledOnceWithExactly(
|
|
53
|
-
store.protect,
|
|
54
|
-
{ name: 'Function', value: 'return a', stacktraceOpts: { constructorOpt: sinon.match.func, prependFrames: [sinon.match.func] } }
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('ssjsInjection() is not called when instrumentation is locked', function () {
|
|
59
|
-
core.scopes.instrumentation.isLocked.returns(true);
|
|
60
|
-
|
|
61
|
-
global.ContrastMethods.Function(constructorArg);
|
|
62
|
-
|
|
63
|
-
expect(core.protect.inputTracing.ssjsInjection).not.to.have.been.called;
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('ssjsInjection() is not called when there is no Protect sourceContext', function () {
|
|
67
|
-
core.scopes.sources.getStore.returns({ protect: null });
|
|
68
|
-
|
|
69
|
-
global.ContrastMethods.Function(constructorArg);
|
|
70
|
-
|
|
71
|
-
expect(core.protect.inputTracing.ssjsInjection).not.to.have.been.called;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('logs an error when there is no `global.ContrastMethods.eval` method', function () {
|
|
75
|
-
global.ContrastMethods.Function = null;
|
|
76
|
-
|
|
77
|
-
core.protect.inputTracing.functionInstrumentation.install();
|
|
78
|
-
|
|
79
|
-
expect(core.logger.error).to.have.been.calledOnceWith('Cannot install `Function` instrumentation - Contrast method DNE');
|
|
80
|
-
});
|
|
81
|
-
});
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const sinon = require('sinon');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const scopes = require('@contrast/scopes');
|
|
6
|
-
const patcher = require('@contrast/patcher');
|
|
7
|
-
const mocks = require('@contrast/test/mocks');
|
|
8
|
-
|
|
9
|
-
describe('protect input-tracing http', function () {
|
|
10
|
-
let core, inputTracing;
|
|
11
|
-
const store = { protect: {} };
|
|
12
|
-
|
|
13
|
-
beforeEach(function () {
|
|
14
|
-
core = mocks.core();
|
|
15
|
-
core.logger = mocks.logger();
|
|
16
|
-
core.patcher = patcher(core);
|
|
17
|
-
core.scopes = scopes(core);
|
|
18
|
-
sinon.stub(core.scopes.sources, 'getStore').returns(store);
|
|
19
|
-
core.depHooks = mocks.depHooks();
|
|
20
|
-
core.protect = mocks.protect();
|
|
21
|
-
require('../../get-source-context')(core);
|
|
22
|
-
({ protect: { inputTracing } } = core);
|
|
23
|
-
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe('http', function () {
|
|
27
|
-
let http;
|
|
28
|
-
|
|
29
|
-
beforeEach(function () {
|
|
30
|
-
http = function () { };
|
|
31
|
-
http.ServerResponse = function () { };
|
|
32
|
-
http.ServerResponse.prototype.end = sinon.stub();
|
|
33
|
-
http.ServerResponse.prototype.write = sinon.stub();
|
|
34
|
-
core.depHooks.resolve.yields(http);
|
|
35
|
-
require('./http')(core).install();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
['write', 'end'].forEach((method) => {
|
|
39
|
-
describe(`instruments ServerResponse.${method}()`, function () {
|
|
40
|
-
it('handleReflectedXss() is called with valid expected values', function () {
|
|
41
|
-
const serverResponse = new http.ServerResponse();
|
|
42
|
-
const value = '" onmouseover="alert(3)"';
|
|
43
|
-
serverResponse[method](value);
|
|
44
|
-
|
|
45
|
-
expect(inputTracing.handleReflectedXss).to.have.been.calledOnce;
|
|
46
|
-
expect(inputTracing.handleReflectedXss).to.have.been.calledWith(
|
|
47
|
-
{},
|
|
48
|
-
{
|
|
49
|
-
name: `http.ServerResponse.prototype.${method}`,
|
|
50
|
-
value,
|
|
51
|
-
stacktraceOpts: {
|
|
52
|
-
constructorOpt: serverResponse[method]
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('handleReflectedXss() is not called if instrumentation is locked', function () {
|
|
59
|
-
sinon.stub(core.scopes.instrumentation, 'isLocked').returns(true);
|
|
60
|
-
const serverResponse = new http.ServerResponse();
|
|
61
|
-
const value = '" onmouseover="alert(3)"';
|
|
62
|
-
serverResponse[method](value);
|
|
63
|
-
|
|
64
|
-
expect(inputTracing.handleReflectedXss).not.to.have.been.called;
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('handleReflectedXss() is not called if there is no sourceContext', function () {
|
|
68
|
-
core.scopes.sources.getStore.returns({ protect: undefined });
|
|
69
|
-
const serverResponse = new http.ServerResponse();
|
|
70
|
-
const value = '" onmouseover="alert(3)"';
|
|
71
|
-
serverResponse[method](value);
|
|
72
|
-
|
|
73
|
-
expect(inputTracing.handleReflectedXss).not.to.have.been.called;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('handleReflectedXss() is not called if there is no value', function () {
|
|
77
|
-
const serverResponse = new http.ServerResponse();
|
|
78
|
-
serverResponse[method]();
|
|
79
|
-
|
|
80
|
-
expect(inputTracing.handleReflectedXss).not.to.have.been.called;
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const sinon = require('sinon');
|
|
4
|
-
const { expect } = require('chai');
|
|
5
|
-
const scopes = require('@contrast/scopes');
|
|
6
|
-
const patcher = require('@contrast/patcher');
|
|
7
|
-
const mocks = require('@contrast/test/mocks');
|
|
8
|
-
|
|
9
|
-
describe('protect input-tracing http2', function () {
|
|
10
|
-
let core, inputTracing;
|
|
11
|
-
const store = { protect: {} };
|
|
12
|
-
|
|
13
|
-
beforeEach(function () {
|
|
14
|
-
core = mocks.core();
|
|
15
|
-
core.logger = mocks.logger();
|
|
16
|
-
core.patcher = patcher(core);
|
|
17
|
-
core.scopes = scopes(core);
|
|
18
|
-
sinon.stub(core.scopes.sources, 'getStore').returns(store);
|
|
19
|
-
core.depHooks = mocks.depHooks();
|
|
20
|
-
core.protect = mocks.protect();
|
|
21
|
-
require('../../get-source-context')(core);
|
|
22
|
-
({ protect: { inputTracing } } = core);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('http2', function () {
|
|
26
|
-
let http2;
|
|
27
|
-
|
|
28
|
-
beforeEach(function () {
|
|
29
|
-
http2 = function () { };
|
|
30
|
-
http2.Http2ServerResponse = function () { };
|
|
31
|
-
http2.Http2ServerResponse.prototype.end = sinon.stub();
|
|
32
|
-
http2.Http2ServerResponse.prototype.write = sinon.stub();
|
|
33
|
-
core.depHooks.resolve.yields(http2);
|
|
34
|
-
require('./http2')(core).install();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
['write', 'end'].forEach((method) => {
|
|
38
|
-
it('handleReflectedXss() is not called if there is no value', function () {
|
|
39
|
-
const serverResponse = new http2.Http2ServerResponse();
|
|
40
|
-
serverResponse[method]();
|
|
41
|
-
|
|
42
|
-
expect(inputTracing.handleReflectedXss).not.to.have.been.called;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('handleReflectedXss() is not called if there is no sourceContext', function () {
|
|
46
|
-
core.scopes.sources.getStore.returns({ protect: undefined });
|
|
47
|
-
const serverResponse = new http2.Http2ServerResponse();
|
|
48
|
-
const value = "<script>alert('xss');</script>";
|
|
49
|
-
serverResponse[method](value);
|
|
50
|
-
|
|
51
|
-
expect(inputTracing.handleReflectedXss).not.to.have.been.called;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('handleReflectedXss() is not called if instrumentation is locked', function () {
|
|
55
|
-
sinon.stub(core.scopes.instrumentation, 'isLocked').returns(true);
|
|
56
|
-
const serverResponse = new http2.Http2ServerResponse();
|
|
57
|
-
const value = "<script>alert('xss');</script>";
|
|
58
|
-
serverResponse[method](value);
|
|
59
|
-
|
|
60
|
-
expect(inputTracing.handleReflectedXss).not.to.have.been.called;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe(`instruments Http2ServerResponse.${method}()`, function () {
|
|
64
|
-
it('handleReflectedXss() is called with valid expected values', function () {
|
|
65
|
-
const serverResponse = new http2.Http2ServerResponse();
|
|
66
|
-
const value = "<script>alert('xss');</script>";
|
|
67
|
-
serverResponse[method](value);
|
|
68
|
-
|
|
69
|
-
expect(inputTracing.handleReflectedXss).to.have.been.calledOnceWith(
|
|
70
|
-
{},
|
|
71
|
-
{
|
|
72
|
-
name: `http2.Http2ServerResponse.prototype.${method}`,
|
|
73
|
-
value,
|
|
74
|
-
stacktraceOpts: {
|
|
75
|
-
constructorOpt: serverResponse[method]
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
});
|