@contrast/protect 1.53.1 → 1.54.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +15 -12
  2. package/lib/error-handlers/common-handler.test.js +0 -52
  3. package/lib/error-handlers/index.test.js +0 -32
  4. package/lib/error-handlers/init-domain.test.js +0 -22
  5. package/lib/error-handlers/install/express.test.js +0 -290
  6. package/lib/error-handlers/install/fastify.test.js +0 -130
  7. package/lib/error-handlers/install/hapi.test.js +0 -102
  8. package/lib/error-handlers/install/koa2.test.js +0 -83
  9. package/lib/error-handlers/install/restify.test.js +0 -57
  10. package/lib/get-source-context.test.js +0 -35
  11. package/lib/hardening/handlers.test.js +0 -89
  12. package/lib/hardening/index.test.js +0 -31
  13. package/lib/hardening/install/node-serialize0.test.js +0 -58
  14. package/lib/index.test.js +0 -53
  15. package/lib/input-analysis/handlers.test.js +0 -1604
  16. package/lib/input-analysis/index.test.js +0 -45
  17. package/lib/input-analysis/install/body-parser1.test.js +0 -134
  18. package/lib/input-analysis/install/busboy1.test.js +0 -81
  19. package/lib/input-analysis/install/cookie-parser1.test.js +0 -144
  20. package/lib/input-analysis/install/express.test.js +0 -241
  21. package/lib/input-analysis/install/fastify.test.js +0 -96
  22. package/lib/input-analysis/install/formidable1.test.js +0 -114
  23. package/lib/input-analysis/install/hapi.test.js +0 -292
  24. package/lib/input-analysis/install/http.test.js +0 -270
  25. package/lib/input-analysis/install/koa-body5.test.js +0 -92
  26. package/lib/input-analysis/install/koa-bodyparser4.test.js +0 -92
  27. package/lib/input-analysis/install/koa2.test.js +0 -259
  28. package/lib/input-analysis/install/multer1.test.js +0 -209
  29. package/lib/input-analysis/install/qs6.test.js +0 -79
  30. package/lib/input-analysis/install/restify.test.js +0 -98
  31. package/lib/input-analysis/install/universal-cookie4.test.js +0 -70
  32. package/lib/input-analysis/ip-analysis.test.js +0 -71
  33. package/lib/input-analysis/virtual-patches.test.js +0 -106
  34. package/lib/input-tracing/handlers/index.test.js +0 -1236
  35. package/lib/input-tracing/index.test.js +0 -62
  36. package/lib/input-tracing/install/child-process.test.js +0 -133
  37. package/lib/input-tracing/install/eval.test.js +0 -78
  38. package/lib/input-tracing/install/fs.test.js +0 -108
  39. package/lib/input-tracing/install/function.test.js +0 -81
  40. package/lib/input-tracing/install/http.test.js +0 -85
  41. package/lib/input-tracing/install/http2.test.js +0 -83
  42. package/lib/input-tracing/install/marsdb.test.js +0 -126
  43. package/lib/input-tracing/install/mongodb.test.js +0 -280
  44. package/lib/input-tracing/install/mssql.test.js +0 -81
  45. package/lib/input-tracing/install/mysql.test.js +0 -108
  46. package/lib/input-tracing/install/postgres.test.js +0 -117
  47. package/lib/input-tracing/install/sequelize.test.js +0 -78
  48. package/lib/input-tracing/install/spdy.test.js +0 -76
  49. package/lib/input-tracing/install/sqlite3.test.js +0 -88
  50. package/lib/input-tracing/install/vm.test.js +0 -176
  51. package/lib/make-response-blocker.test.js +0 -99
  52. package/lib/make-source-context.test.js +0 -219
  53. package/lib/policy.test.js +0 -446
  54. package/lib/semantic-analysis/handlers.test.js +0 -379
  55. package/lib/semantic-analysis/index.test.js +0 -38
  56. package/lib/semantic-analysis/install/libxmljs.test.js +0 -156
  57. package/lib/semantic-analysis/utils/xml-analysis.test.js +0 -156
  58. package/lib/throw-security-exception.test.js +0 -37
@@ -1,126 +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
- const { patchType } = require('../constants');
9
- const methods = ['find', 'findOne', 'update', 'insert', 'remove', 'ids', 'count'];
10
-
11
- describe('protect input-tracing marsdb', function () {
12
- const sourceContext = {};
13
- const store = { protect: sourceContext };
14
-
15
- let core, inputTracing, mockMarsDb, marsdbInstr;
16
-
17
- beforeEach(function () {
18
- core = mocks.core();
19
- core.logger = mocks.logger();
20
- core.patcher = patcher(core);
21
- core.scopes = scopes(core);
22
- sinon.stub(core.scopes.sources, 'getStore').returns(store);
23
- core.depHooks = mocks.depHooks();
24
- core.protect = mocks.protect();
25
- require('../../get-source-context')(core);
26
- ({ protect: { inputTracing } } = core);
27
-
28
- sinon.spy(core.patcher, 'patch');
29
-
30
- mockMarsDb = {
31
- Collection: function Collection() { },
32
- };
33
- methods.forEach((method) => {
34
- mockMarsDb.Collection.prototype[method] = () => { };
35
- });
36
-
37
- core.depHooks.resolve.yields(mockMarsDb);
38
-
39
- marsdbInstr = require('./marsdb')(core);
40
- });
41
-
42
- describe('patcher patches', function () {
43
- it('patches all relevant objects in marsdb', function () {
44
- marsdbInstr.install();
45
- expect(core.patcher.patch).to.have.callCount(methods.length);
46
-
47
- methods.forEach((method) => {
48
- expect(core.patcher.patch).to.have.been.calledWithMatch(
49
- mockMarsDb.Collection.prototype, method, {
50
- name: `marsdb.Collection.prototype.${method}`,
51
- patchType,
52
- pre: sinon.match.func
53
- }
54
- );
55
- });
56
- });
57
- });
58
-
59
- describe('patcher pre-hooks', function () {
60
- let hooksFns;
61
- const correctArg = { id: 'some-query' };
62
- const incorrectArgs = [null, '', undefined, {}];
63
- const captureStackTraceArgs = (method) => ([
64
- {
65
- name: `marsdb.Collection.prototype.${method}`,
66
- value: correctArg
67
- }, { constructorOpt: sinon.match.func, prependFrames: [sinon.match.func] }
68
- ]);
69
-
70
- const inputTracingNosqlInjectionArgs = (method) => ([sourceContext,
71
- {
72
- name: `marsdb.Collection.prototype.${method}`,
73
- value: correctArg
74
- }]);
75
-
76
- beforeEach(function () {
77
- marsdbInstr.install();
78
- hooksFns = methods.reduce((acc, method) => {
79
- acc[method] = new mockMarsDb.Collection()[method];
80
-
81
- return acc;
82
- }, {});
83
- });
84
-
85
- methods.forEach((method) => {
86
- it(`marsdb.Collection.prototype.${method} calls \`inputTracing.nosqlInjectionMongo\` when called with expected arguments`, function () {
87
- const fn = hooksFns[method];
88
-
89
- fn(correctArg);
90
-
91
- const stackTraceArgs = captureStackTraceArgs(method);
92
- const inputTracingArgs = inputTracingNosqlInjectionArgs(method);
93
- expect(inputTracing.nosqlInjectionMongo).to.have.been.calledWith(inputTracingArgs[0], {
94
- ...inputTracingArgs[1],
95
- stacktraceData: {
96
- constructorOpt: stackTraceArgs[1].constructorOpt, prependFrames: stackTraceArgs[1].prependFrames
97
- }
98
- });
99
- });
100
-
101
- it(`marsdb.Collection.prototype.${method} does not call \`inputTracing.nosqlInjectionMongo\` and \`core.captureStacktrace\` when called with wrong/no arguments`, function () {
102
- const fn = hooksFns[method];
103
-
104
- for (let i = 0; i < incorrectArgs.length; i++) {
105
- fn(incorrectArgs[i]);
106
-
107
- expect(core.captureStacktrace).to.not.have.been.called;
108
- expect(inputTracing.nosqlInjectionMongo).to.not.have.been.called;
109
- }
110
- });
111
-
112
- it(`marsdb.Collection.prototype.${method} does not call \`inputTracing.nosqlInjectionMongo\` and \`core.captureStacktrace\` when there is no sourceContext`, function () {
113
- const fn = hooksFns[method];
114
-
115
- core.scopes.sources.getStore.returns(null);
116
-
117
- fn(correctArg);
118
-
119
- expect(core.captureStacktrace).to.not.have.been.called;
120
- expect(inputTracing.nosqlInjectionMongo).to.not.have.been.called;
121
- });
122
- });
123
-
124
- });
125
- });
126
-
@@ -1,280 +0,0 @@
1
- 'use strict';
2
-
3
- const sinon = require('sinon');
4
- const { expect } = require('chai');
5
- const { initProtectFixture } = require('@contrast/test/fixtures');
6
-
7
- describe('protect input-tracing mongodb', function() {
8
- let core, instr, simulateRequestScope, nosqlInjectionMongo;
9
-
10
- class Db {
11
- command() { }
12
- eval() { }
13
- aggregate() { }
14
- }
15
-
16
- class Collection {
17
- find() { }
18
- findOne() { }
19
- findAndModify() { }
20
- findOneAndDelete() { }
21
- findOneAndReplace() { }
22
- findOneAndUpdate() { }
23
- remove() { }
24
- removeOne() { }
25
- replaceOne() { }
26
- removeMany() { }
27
- rename() { }
28
- update() { }
29
- updateOne() { }
30
- updateMany() { }
31
- deleteOne() { }
32
- deleteMany() { }
33
- aggregate() { }
34
- mapReduce() { }
35
- group() { }
36
- }
37
-
38
- before(function() {
39
- ({ core, simulateRequestScope } = initProtectFixture());
40
- require('../../get-source-context')(core);
41
-
42
- core.depHooks.resolve.yields({ Collection, Db });
43
-
44
- instr = require('./mongodb')(core);
45
- instr.install();
46
- });
47
-
48
- beforeEach(function() {
49
- sinon.stub(core.protect.inputTracing, 'nosqlInjectionMongo');
50
- ({ nosqlInjectionMongo } = core.protect.inputTracing);
51
- });
52
-
53
- [
54
- { subject: Collection, method: 'find' },
55
- { subject: Collection, method: 'findOne' },
56
- { subject: Collection, method: 'findAndModify' },
57
- { subject: Collection, method: 'findOneAndDelete' },
58
- { subject: Collection, method: 'findOneAndReplace' },
59
- { subject: Collection, method: 'findOneAndUpdate' },
60
- { subject: Collection, method: 'remove' },
61
- { subject: Collection, method: 'replaceOne' },
62
- { subject: Collection, method: 'update' },
63
- { subject: Collection, method: 'updateOne' },
64
- { subject: Collection, method: 'updateMany' },
65
- { subject: Collection, method: 'deleteOne' },
66
- { subject: Collection, method: 'deleteMany' },
67
- { subject: Db, method: 'command' },
68
- ].forEach(({ subject, method }) => {
69
- describe(`${subject.name}.prototype.${method}()`, function() {
70
- it('skips instrumentation if assess store is missing', function() {
71
- simulateRequestScope(() => {
72
- const expObject = { $ne: 'test' };
73
-
74
- (new subject())[method]({ expObject });
75
-
76
- expect(nosqlInjectionMongo).not.to.have.been.called;
77
- }, {});
78
- });
79
-
80
- it('skips instrumentation if the argument is not a string or an non-empty object', function() {
81
- simulateRequestScope(function() {
82
- (new subject())[method]({});
83
- expect(nosqlInjectionMongo).not.to.have.been.called;
84
- });
85
- });
86
-
87
- it('analyzes the input for a nosql-injection with string input', function() {
88
- simulateRequestScope(function() {
89
- const attackString = 'sleep(1)';
90
- const sc = core.scopes.sources.getStore()?.protect;
91
-
92
- (new subject())[method](attackString);
93
-
94
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString, name: `mongodb.${subject.name}.prototype.${method}` });
95
- });
96
- });
97
-
98
- it('analyzes the input for a nosql-injection with an object input', function() {
99
- simulateRequestScope(function() {
100
- const expObject = { $ne: 'test' };
101
- const sc = core.scopes.sources.getStore()?.protect;
102
-
103
- (new subject())[method]({ expObject });
104
-
105
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: { expObject }, name: `mongodb.${subject.name}.prototype.${method}` });
106
- });
107
- });
108
- });
109
- });
110
-
111
- describe('Db.prototype.aggregate and Collection.prototype.aggregate', function() {
112
- it('analyzes for a nosql-injection from user input in the $function operator', function() {
113
- simulateRequestScope(function() {
114
- const sc = core.scopes.sources.getStore()?.protect;
115
- const attackString = 'sleep(1)';
116
- (new Collection()).aggregate([
117
- {
118
- $function: {
119
- body: attackString
120
- }
121
- }
122
- ]);
123
- (new Db()).aggregate([
124
- {
125
- $function: {
126
- body: attackString
127
- }
128
- }
129
- ]);
130
-
131
- expect(nosqlInjectionMongo).to.have.been.calledTwice;
132
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString, name: 'mongodb.Db.prototype.aggregate' });
133
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString, name: 'mongodb.Collection.prototype.aggregate' });
134
- });
135
- });
136
-
137
- [
138
- 'init',
139
- 'merge',
140
- 'accumulate',
141
- 'finalize'
142
- ].forEach((prop) => {
143
- it(`analyzes for a nosql-injection from user input in the $accumulator operator and ${prop} property`, function() {
144
- simulateRequestScope(function() {
145
- const attackString = 'sleep(1)';
146
- const sc = core.scopes.sources.getStore()?.protect;
147
- (new Collection()).aggregate([
148
- {
149
- $accumulator: {
150
- [prop]: attackString
151
- }
152
- }
153
- ]);
154
-
155
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString, name: 'mongodb.Collection.prototype.aggregate' });
156
- });
157
- });
158
- });
159
- });
160
-
161
- describe('Collection.prototype.mapReduce', function() {
162
- it('analyzes for a nosql-injection from user input in the first 2 arguments of `mapReduce` method', function() {
163
- const options = { options: 'something' };
164
- simulateRequestScope(function() {
165
- const attackString1 = 'sleep(1)';
166
- const attackString2 = 'sleep(2)';
167
- const sc = core.scopes.sources.getStore()?.protect;
168
- (new Collection()).mapReduce(
169
- attackString1,
170
- 'devData#1',
171
- options
172
- );
173
- (new Collection()).mapReduce(
174
- 'devData#2',
175
- attackString2,
176
- options
177
- );
178
-
179
- expect(nosqlInjectionMongo).to.have.a.callCount(4);
180
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString1, name: 'mongodb.Collection.prototype.mapReduce' });
181
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: 'devData#1', name: 'mongodb.Collection.prototype.mapReduce' });
182
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString2, name: 'mongodb.Collection.prototype.mapReduce' });
183
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: 'devData#2', name: 'mongodb.Collection.prototype.mapReduce' });
184
- });
185
- });
186
-
187
- it('analyzes for a nosql-injection from user input in the third argument of `mapReduce` method', function() {
188
- simulateRequestScope(function() {
189
- const attackString = 'sleep(1)';
190
- const expObj = { $ne: 'test' };
191
- const options1 = { query: { expObj } };
192
- const options2 = { finalize: attackString };
193
- const sc = core.scopes.sources.getStore()?.protect;
194
- (new Collection()).mapReduce(
195
- 'devData#1',
196
- 'devData#2',
197
- options1
198
- );
199
- (new Collection()).mapReduce(
200
- 'devData#3',
201
- 'devData#4',
202
- options2
203
- );
204
-
205
- expect(nosqlInjectionMongo).to.have.a.callCount(6);
206
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: 'devData#1', name: 'mongodb.Collection.prototype.mapReduce' });
207
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: 'devData#2', name: 'mongodb.Collection.prototype.mapReduce' });
208
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString, name: 'mongodb.Collection.prototype.mapReduce' });
209
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: 'devData#3', name: 'mongodb.Collection.prototype.mapReduce' });
210
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: 'devData#4', name: 'mongodb.Collection.prototype.mapReduce' });
211
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: { expObj }, name: 'mongodb.Collection.prototype.mapReduce' });
212
- });
213
- });
214
- });
215
-
216
- describe('Collection.prototype.group', function() {
217
- it('analyzes for a nosql-injection from user input in the first, the second and the fourth argument of `group` method', function() {
218
- simulateRequestScope(function() {
219
- const attackString1 = 'sleep(1)';
220
- const attackString2 = 'sleep(2)';
221
- const condition = { expObj: { $ne: 'test' } };
222
- const initState = { init: 'state' };
223
- const sc = core.scopes.sources.getStore()?.protect;
224
- (new Collection()).group(
225
- attackString1,
226
- condition,
227
- initState,
228
- attackString2
229
- );
230
-
231
- expect(nosqlInjectionMongo).to.have.a.callCount(3);
232
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString1, name: 'mongodb.Collection.prototype.group' });
233
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString2, name: 'mongodb.Collection.prototype.group' });
234
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: { expObj: { $ne: 'test' } }, name: 'mongodb.Collection.prototype.group' });
235
- });
236
- });
237
- });
238
-
239
- describe('Db.prototype.eval() and other edge cases', function() {
240
- it('skips patching if the method is missing', function() {
241
- class Collection {
242
- findOne() { }
243
- }
244
- class Db {
245
- command() { }
246
- }
247
- core.depHooks.resolve
248
- .withArgs(sinon.match({ name: 'mongodb' }))
249
- .yields({ Collection, Db }, 'v5.x.x');
250
-
251
- const instr = require('./mongodb')(core);
252
- instr.install();
253
- expect(core.logger.trace).to.have.been.calledWith({ name: 'mongodb.Db.prototype.eval', version: 'v5.x.x' }, 'method not found - skipping instrumentation');
254
- expect(core.logger.trace).to.have.been.calledWith({ name: 'mongodb.Collection.prototype.findOneAndDelete', version: 'v5.x.x' }, 'method not found - skipping instrumentation');
255
- });
256
-
257
- it('analyzes for a nosql-injection from the eval methhod', function() {
258
- simulateRequestScope(function() {
259
- const attackString = 'sleep(1)';
260
- const sc = core.scopes.sources.getStore()?.protect;
261
- (new Db()).eval(attackString);
262
-
263
- expect(nosqlInjectionMongo).to.have.a.callCount(1);
264
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: attackString, name: 'mongodb.Db.prototype.eval' });
265
- });
266
- });
267
-
268
- it('analyzes the `.filter` property on a command method', function() {
269
- simulateRequestScope(function() {
270
- const expObject = { $ne: 'test' };
271
- const sc = core.scopes.sources.getStore()?.protect;
272
-
273
- (new Db()).command({ filter: { expObject } });
274
-
275
- expect(nosqlInjectionMongo).to.have.been.calledWithMatch(sc, { value: { expObject }, name: 'mongodb.Db.prototype.command' });
276
- });
277
- });
278
- });
279
- });
280
-
@@ -1,81 +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 mssql', function () {
10
- class PreparedStatement { }
11
- class Request { }
12
- let core, handleSqlInjection;
13
-
14
- beforeEach(function () {
15
- core = mocks.core();
16
- core.logger = mocks.logger();
17
- core.patcher = patcher(core);
18
- core.scopes = scopes(core);
19
- sinon.stub(core.scopes.sources, 'getStore').returns({ protect: {} });
20
- core.depHooks = mocks.depHooks();
21
- core.protect = mocks.protect();
22
- handleSqlInjection = core.protect.inputTracing.handleSqlInjection;
23
- require('../../get-source-context')(core);
24
-
25
- PreparedStatement.prototype.prepare = sinon.stub();
26
- Request.prototype.batch = sinon.stub();
27
- Request.prototype.query = sinon.stub();
28
-
29
- core.depHooks.resolve
30
- .withArgs(sinon.match({ file: 'lib/base/prepared-statement.js' }))
31
- .yields(PreparedStatement);
32
-
33
- core.depHooks.resolve
34
- .withArgs(sinon.match({ file: 'lib/base/request.js' }))
35
- .yields(Request);
36
-
37
- require('./mssql')(core).install();
38
- });
39
-
40
- [
41
- { subject: PreparedStatement, method: 'prepare' },
42
- { subject: Request, method: 'batch' },
43
- { subject: Request, method: 'query' },
44
- ].forEach(({ subject, method }) => {
45
- describe(`${subject.name}.prototype.${method}()`, function () {
46
- it('does not call handleSqlInjection() if there is no sourceContext', function () {
47
- core.scopes.sources.getStore.returns({});
48
-
49
- subject.prototype[method]();
50
- expect(handleSqlInjection).not.to.have.been.called;
51
- });
52
-
53
- it('does not call handleSqlInjection() if there is no argument', function () {
54
- subject.prototype[method]();
55
- expect(handleSqlInjection).not.to.have.been.called;
56
- });
57
-
58
- it('does not call handleSqlInjection() if the argument is not a string', function () {
59
- subject.prototype[method](4);
60
- expect(handleSqlInjection).not.to.have.been.called;
61
- });
62
-
63
- it('calls handleSqlInjection() as expected', function () {
64
- const value = ';drop table Foo--';
65
-
66
- subject.prototype[method](value);
67
- expect(handleSqlInjection).to.have.been.calledWith(
68
- {},
69
- {
70
- name: `mssql.${subject.name}.prototype.${method}`,
71
- value,
72
- stacktraceOpts: {
73
- constructorOpt: subject.prototype[method],
74
- prependFrames: [sinon.match.func],
75
- },
76
- },
77
- );
78
- });
79
- });
80
- });
81
- });
@@ -1,108 +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 mysql', 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
- core.depHooks = mocks.depHooks();
19
- core.protect = mocks.protect();
20
- require('../../get-source-context')(core);
21
- inputTracing = core.protect.inputTracing;
22
-
23
-
24
- sinon.stub(core.scopes.sources, 'getStore').returns(store);
25
- });
26
-
27
- describe('mysql', function () {
28
- let Connection;
29
-
30
- beforeEach(function () {
31
- Connection = function () { };
32
- Connection.prototype.query = sinon.stub();
33
- core.depHooks.resolve.yields(Connection);
34
- require('./mysql')(core).install();
35
- });
36
-
37
- describe('instruments connection.query()', function () {
38
- it('handleSqlInjection() is called with valid expected values', function () {
39
- const conn = new Connection();
40
- const value = 'SELECT "foo"';
41
- conn.query(value);
42
-
43
- expect(inputTracing.handleSqlInjection).to.have.been.calledWith(
44
- {},
45
- { name: 'mysql.Connection.prototype.query', value, stacktraceOpts: { constructorOpt: conn.query, prependFrames: [sinon.match.func] } }
46
- );
47
- });
48
-
49
- it('handleSqlInjection() is not called if there is no sourceContext', function () {
50
- core.scopes.sources.getStore.returns({ protect: undefined });
51
- const conn = new Connection();
52
- const value = 'SELECT "foo"';
53
- conn.query(value);
54
-
55
- expect(inputTracing.handleSqlInjection).not.to.have.been.called;
56
- });
57
-
58
- it('handleSqlInjection() is not called if the sql value is empty or not a string', function () {
59
- const conn = new Connection();
60
- conn.query('');
61
- conn.query(100);
62
-
63
- expect(inputTracing.handleSqlInjection).not.to.have.been.called;
64
- });
65
- });
66
- });
67
-
68
- describe('mysql2', function () {
69
- let Connection;
70
-
71
- beforeEach(function () {
72
- Connection = function () { };
73
- Connection.prototype.execute = sinon.stub();
74
- core.depHooks.resolve.yields(Connection);
75
- require('./mysql')(core).install();
76
- });
77
-
78
- describe('instruments connection.execute()', function () {
79
- it('handleSqlInjection() is called with expected values', function () {
80
- const conn = new Connection();
81
- const value = 'SELECT "foo"';
82
- conn.execute(value);
83
-
84
- expect(inputTracing.handleSqlInjection).to.have.been.calledWith(
85
- {},
86
- { name: 'mysql2.Connection.prototype.execute', value, stacktraceOpts: { constructorOpt: conn.execute, prependFrames: [sinon.match.func] } }
87
- );
88
- });
89
-
90
- it('handleSqlInjection() is not called if there is no sourceContext', function () {
91
- core.scopes.sources.getStore.returns({ protect: undefined });
92
- const conn = new Connection();
93
- const value = 'SELECT "foo"';
94
- conn.execute(value);
95
-
96
- expect(inputTracing.handleSqlInjection).not.to.have.been.called;
97
- });
98
-
99
- it('handleSqlInjection() is not called if the sql value is empty or not a string', function () {
100
- const conn = new Connection();
101
- conn.execute('');
102
- conn.execute(100);
103
-
104
- expect(inputTracing.handleSqlInjection).not.to.have.been.called;
105
- });
106
- });
107
- });
108
- });