@contrast/protect 1.48.0 → 1.50.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/error-handlers/index.js +1 -1
- package/lib/error-handlers/index.test.js +1 -1
- package/lib/error-handlers/install/express.js +162 -0
- package/lib/error-handlers/install/express.test.js +290 -0
- package/lib/error-handlers/install/hapi.js +2 -2
- package/lib/error-handlers/install/hapi.test.js +2 -2
- package/lib/error-handlers/install/koa2.js +1 -1
- package/lib/error-handlers/install/restify.js +1 -1
- package/lib/error-handlers/install/restify.test.js +1 -1
- package/lib/hardening/install/node-serialize0.js +2 -2
- package/lib/hardening/install/node-serialize0.test.js +1 -4
- package/lib/index.d.ts +1 -1
- package/lib/input-analysis/index.js +1 -1
- package/lib/input-analysis/index.test.js +1 -1
- package/lib/input-analysis/install/body-parser1.js +2 -2
- package/lib/input-analysis/install/busboy1.js +1 -1
- package/lib/input-analysis/install/cookie-parser1.js +1 -1
- package/lib/input-analysis/install/{express4.js → express.js} +61 -20
- package/lib/input-analysis/install/{express4.test.js → express.test.js} +92 -59
- package/lib/input-analysis/install/formidable1.js +1 -1
- package/lib/input-analysis/install/hapi.js +1 -1
- package/lib/input-analysis/install/hapi.test.js +6 -14
- package/lib/input-analysis/install/koa-body5.js +1 -1
- package/lib/input-analysis/install/koa-bodyparser4.js +1 -1
- package/lib/input-analysis/install/koa2.js +5 -5
- package/lib/input-analysis/install/multer1.js +1 -1
- package/lib/input-analysis/install/qs6.js +1 -1
- package/lib/input-analysis/install/restify.js +1 -1
- package/lib/input-analysis/install/restify.test.js +1 -1
- package/lib/input-analysis/install/universal-cookie4.js +1 -1
- package/lib/input-tracing/install/child-process.js +1 -1
- package/lib/input-tracing/install/fs.js +2 -2
- package/lib/input-tracing/install/fs.test.js +2 -2
- package/lib/input-tracing/install/http.js +2 -2
- package/lib/input-tracing/install/http2.js +2 -2
- package/lib/input-tracing/install/marsdb.js +2 -2
- package/lib/input-tracing/install/marsdb.test.js +1 -1
- package/lib/input-tracing/install/mongodb.js +2 -2
- package/lib/input-tracing/install/mongodb.test.js +2 -4
- package/lib/input-tracing/install/mssql.js +3 -3
- package/lib/input-tracing/install/mssql.test.js +2 -2
- package/lib/input-tracing/install/mysql.js +7 -9
- package/lib/input-tracing/install/postgres.js +3 -3
- package/lib/input-tracing/install/postgres.test.js +2 -10
- package/lib/input-tracing/install/sequelize.js +2 -2
- package/lib/input-tracing/install/spdy.js +2 -2
- package/lib/input-tracing/install/sqlite3.js +2 -2
- package/lib/input-tracing/install/vm.js +2 -2
- package/lib/semantic-analysis/install/libxmljs.js +3 -3
- package/lib/semantic-analysis/install/libxmljs.test.js +2 -2
- package/package.json +11 -11
- package/lib/error-handlers/install/express4.js +0 -138
- package/lib/error-handlers/install/express4.test.js +0 -238
|
@@ -32,12 +32,34 @@ module.exports = (core) => {
|
|
|
32
32
|
protect: { inputAnalysis },
|
|
33
33
|
} = core;
|
|
34
34
|
|
|
35
|
+
function layerPostHook(name) {
|
|
36
|
+
return function(data) {
|
|
37
|
+
const layer = data.obj;
|
|
38
|
+
|
|
39
|
+
// we can exit early if
|
|
40
|
+
// the layer doesn't match the request or
|
|
41
|
+
// the layer doesn't recognize any parameters
|
|
42
|
+
if (!data.result || !layer.keys || layer.keys.length === 0 || layer.route?.path === '*') {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const sourceContext = protect.getSourceContext(name);
|
|
47
|
+
|
|
48
|
+
if (!sourceContext) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
sourceContext.parsedParams = layer.params;
|
|
53
|
+
inputAnalysis.handleUrlParams(sourceContext, layer.params);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
35
57
|
/**
|
|
36
58
|
* registers a depHook for express module instrumentation
|
|
37
59
|
*/
|
|
38
60
|
function install() {
|
|
39
61
|
depHooks.resolve(
|
|
40
|
-
{ name: 'express', version: '
|
|
62
|
+
{ name: 'express', version: '4', file: 'lib/middleware/query.js' },
|
|
41
63
|
(query) => patcher.patch(query, {
|
|
42
64
|
name: 'express.query',
|
|
43
65
|
patchType,
|
|
@@ -84,40 +106,59 @@ module.exports = (core) => {
|
|
|
84
106
|
}));
|
|
85
107
|
|
|
86
108
|
depHooks.resolve(
|
|
87
|
-
{ name: 'express', version: '
|
|
109
|
+
{ name: 'express', version: '4', file: 'lib/router/layer.js' },
|
|
88
110
|
(Layer) => {
|
|
89
111
|
const name = 'express.Layer.prototype.match';
|
|
90
112
|
patcher.patch(Layer.prototype, 'match', {
|
|
91
113
|
name,
|
|
92
114
|
patchType,
|
|
93
|
-
post(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// we can exit early if
|
|
97
|
-
// the layer doesn't match the request or
|
|
98
|
-
// the layer doesn't recognize any parameters
|
|
99
|
-
if (!data.result || !layer.keys || layer.keys.length === 0 || layer.route?.path === '*') {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
115
|
+
post: layerPostHook(name)
|
|
116
|
+
});
|
|
102
117
|
|
|
103
|
-
|
|
118
|
+
return Layer;
|
|
119
|
+
});
|
|
104
120
|
|
|
105
|
-
|
|
106
|
-
|
|
121
|
+
depHooks.resolve(
|
|
122
|
+
{ name: 'express', version: '5', file: 'lib/request.js' },
|
|
123
|
+
(request) => {
|
|
124
|
+
const { get } = Object.getOwnPropertyDescriptor(request, 'query');
|
|
125
|
+
const patchedGet = patcher.patch(get, {
|
|
126
|
+
name: 'request.query.get',
|
|
127
|
+
patchType,
|
|
128
|
+
post(data) {
|
|
129
|
+
const query = data.result;
|
|
130
|
+
if (query && Object.keys(query).length) {
|
|
131
|
+
const sourceContext = protect.getSourceContext();
|
|
132
|
+
if (sourceContext && !('parsedQuery' in sourceContext)) {
|
|
133
|
+
sourceContext.parsedQuery = query;
|
|
134
|
+
inputAnalysis.handleQueryParams(sourceContext, query);
|
|
135
|
+
}
|
|
107
136
|
}
|
|
108
|
-
|
|
109
|
-
sourceContext.parsedParams = layer.params;
|
|
110
|
-
inputAnalysis.handleUrlParams(sourceContext, layer.params);
|
|
111
137
|
}
|
|
112
138
|
});
|
|
139
|
+
Object.defineProperty(request, 'query', {
|
|
140
|
+
get: patchedGet
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
);
|
|
113
144
|
|
|
145
|
+
depHooks.resolve(
|
|
146
|
+
{ name: 'router', version: '2', file: 'lib/layer.js' },
|
|
147
|
+
(Layer) => {
|
|
148
|
+
const name = 'Layer.prototype.match';
|
|
149
|
+
patcher.patch(Layer.prototype, 'match', {
|
|
150
|
+
name,
|
|
151
|
+
patchType,
|
|
152
|
+
post: layerPostHook(name)
|
|
153
|
+
});
|
|
114
154
|
return Layer;
|
|
115
|
-
}
|
|
155
|
+
}
|
|
156
|
+
);
|
|
116
157
|
}
|
|
117
158
|
|
|
118
|
-
const
|
|
159
|
+
const expressInstrumentation = inputAnalysis.expressInstrumentation = {
|
|
119
160
|
install
|
|
120
161
|
};
|
|
121
162
|
|
|
122
|
-
return
|
|
163
|
+
return expressInstrumentation;
|
|
123
164
|
};
|
|
@@ -7,12 +7,13 @@ const patcher = require('@contrast/patcher');
|
|
|
7
7
|
const mocks = require('@contrast/test/mocks');
|
|
8
8
|
const SecurityException = require('../../security-exception');
|
|
9
9
|
const secEx = SecurityException.create();
|
|
10
|
-
const expressInstr = require('./
|
|
10
|
+
const expressInstr = require('./express');
|
|
11
11
|
|
|
12
|
-
describe('protect input-analysis express
|
|
12
|
+
describe('protect input-analysis express', function () {
|
|
13
13
|
let core,
|
|
14
14
|
inputAnalysis,
|
|
15
15
|
expressQueryMock,
|
|
16
|
+
requestMock,
|
|
16
17
|
nextStub,
|
|
17
18
|
query,
|
|
18
19
|
Layer;
|
|
@@ -33,11 +34,17 @@ describe('protect input-analysis express v4.x', function () {
|
|
|
33
34
|
next();
|
|
34
35
|
};
|
|
35
36
|
|
|
37
|
+
requestMock = {
|
|
38
|
+
get query() {
|
|
39
|
+
return { parameter: 'parsed-query' };
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
36
43
|
Layer = sinon.stub();
|
|
37
44
|
Layer.prototype.match = sinon.stub().returns(true);
|
|
38
45
|
|
|
39
|
-
core.depHooks.resolve.withArgs({ name: 'express', version: '
|
|
40
|
-
core.depHooks.resolve.withArgs({ name: 'express', version: '
|
|
46
|
+
core.depHooks.resolve.withArgs({ name: 'express', version: '4', file: 'lib/middleware/query.js' }).yields(expressQueryMock);
|
|
47
|
+
core.depHooks.resolve.withArgs({ name: 'express', version: '5', file: 'lib/request.js' }).yields(requestMock);
|
|
41
48
|
|
|
42
49
|
nextStub = sinon.stub();
|
|
43
50
|
|
|
@@ -47,22 +54,7 @@ describe('protect input-analysis express v4.x', function () {
|
|
|
47
54
|
core.patcher.patch.resetHistory();
|
|
48
55
|
});
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
expressInstr(core).install();
|
|
52
|
-
expect(core.patcher.patch).to.have.callCount(2);
|
|
53
|
-
expect(core.patcher.patch).to.have.been.calledWithMatch(expressQueryMock, {
|
|
54
|
-
name: 'express.query',
|
|
55
|
-
patchType: 'protect-input-analysis',
|
|
56
|
-
post: sinon.match.func
|
|
57
|
-
});
|
|
58
|
-
expect(core.patcher.patch).to.have.been.calledWithMatch(Layer.prototype, 'match', {
|
|
59
|
-
name: 'express.Layer.prototype.match',
|
|
60
|
-
patchType: 'protect-input-analysis',
|
|
61
|
-
post: sinon.match.func
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe('express.query patch', function () {
|
|
57
|
+
describe('express4 query patch', function () {
|
|
66
58
|
it('calls `.handleQueryParams` when parsing is successful and in right context', function () {
|
|
67
59
|
core.scopes.sources.run({ protect: {} }, () => {
|
|
68
60
|
const queryParser = expressQueryMock(query);
|
|
@@ -98,7 +90,6 @@ describe('protect input-analysis express v4.x', function () {
|
|
|
98
90
|
});
|
|
99
91
|
|
|
100
92
|
expect(inputAnalysis.handleQueryParams).not.to.have.been.called;
|
|
101
|
-
expect(core.logger.debug).not.to.have.been.called;
|
|
102
93
|
expect(nextStub).to.have.been.calledOnce;
|
|
103
94
|
});
|
|
104
95
|
|
|
@@ -109,7 +100,6 @@ describe('protect input-analysis express v4.x', function () {
|
|
|
109
100
|
});
|
|
110
101
|
|
|
111
102
|
expect(inputAnalysis.handleQueryParams).not.to.have.been.called;
|
|
112
|
-
expect(core.logger.debug).not.to.have.been.called;
|
|
113
103
|
expect(nextStub).to.have.been.calledOnce;
|
|
114
104
|
});
|
|
115
105
|
|
|
@@ -141,68 +131,111 @@ describe('protect input-analysis express v4.x', function () {
|
|
|
141
131
|
});
|
|
142
132
|
});
|
|
143
133
|
|
|
144
|
-
describe('
|
|
145
|
-
|
|
134
|
+
describe('express5 query get patch', function() {
|
|
135
|
+
it('does not call `.handleQueryParams` when not in context', function () {
|
|
136
|
+
core.scopes.sources.run({}, () => {
|
|
137
|
+
requestMock.query;
|
|
138
|
+
});
|
|
146
139
|
|
|
147
|
-
|
|
148
|
-
layer = { keys: ['foo'], params: { foo: 'bar' }, route: { path: '/test' } };
|
|
140
|
+
expect(inputAnalysis.handleQueryParams).not.to.have.been.called;
|
|
149
141
|
});
|
|
150
142
|
|
|
151
|
-
it('
|
|
143
|
+
it('does not call `.handleQueryParams` when no query exists', function () {
|
|
144
|
+
requestMock = {
|
|
145
|
+
get query() {
|
|
146
|
+
return {};
|
|
147
|
+
}
|
|
148
|
+
};
|
|
152
149
|
core.scopes.sources.run({ protect: {} }, () => {
|
|
153
|
-
|
|
150
|
+
requestMock.query;
|
|
154
151
|
});
|
|
155
152
|
|
|
156
|
-
expect(inputAnalysis.
|
|
157
|
-
expect(inputAnalysis.handleUrlParams).to.have.been.calledWithMatch({ parsedParams: layer.params }, layer.params);
|
|
153
|
+
expect(inputAnalysis.handleQueryParams).not.to.have.been.called;
|
|
158
154
|
});
|
|
159
155
|
|
|
160
|
-
it('does not call `.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
core.scopes.sources.run({}, () => {
|
|
164
|
-
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
156
|
+
it('does not call `.handleQueryParams` when query was already parsed', function () {
|
|
157
|
+
core.scopes.sources.run({ protect: { parsedQuery: query } }, () => {
|
|
158
|
+
requestMock.query;
|
|
165
159
|
});
|
|
166
160
|
|
|
167
|
-
expect(inputAnalysis.
|
|
168
|
-
expect(core.logger.debug).not.to.have.been.called;
|
|
161
|
+
expect(inputAnalysis.handleQueryParams).not.to.have.been.called;
|
|
169
162
|
});
|
|
170
163
|
|
|
171
|
-
it('
|
|
172
|
-
core.scopes.sources.run({}, () => {
|
|
173
|
-
|
|
164
|
+
it('calls `.handleQueryParams` when parsing is successful and in right context', function () {
|
|
165
|
+
core.scopes.sources.run({ protect: {} }, () => {
|
|
166
|
+
requestMock.query;
|
|
174
167
|
});
|
|
175
168
|
|
|
176
|
-
expect(inputAnalysis.
|
|
177
|
-
expect(
|
|
169
|
+
expect(inputAnalysis.handleQueryParams).to.have.been.calledOnce;
|
|
170
|
+
expect(inputAnalysis.handleQueryParams).to.have.been.calledWithMatch({ parsedQuery: query }, query);
|
|
178
171
|
});
|
|
172
|
+
});
|
|
179
173
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
174
|
+
['4', '5'].forEach((v) => {
|
|
175
|
+
describe(`express${v} Layer.prototype.match`, function() {
|
|
176
|
+
let layer;
|
|
177
|
+
beforeEach(function() {
|
|
178
|
+
const args = v === '4'
|
|
179
|
+
? { name: 'express', version: '4', file: 'lib/router/layer.js' }
|
|
180
|
+
: { name: 'router', version: '2', file: 'lib/layer.js' };
|
|
181
|
+
core.depHooks.resolve.withArgs(args).yields(Layer);
|
|
182
|
+
expressInstr(core).install();
|
|
183
|
+
layer = { keys: ['foo'], params: { foo: 'bar' }, route: { path: '/test' } };
|
|
183
184
|
});
|
|
184
185
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
it('calls `.handleUrlParams` when parsing is successful and in right context', function () {
|
|
187
|
+
core.scopes.sources.run({ protect: {} }, () => {
|
|
188
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
189
|
+
});
|
|
188
190
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
191
|
+
expect(inputAnalysis.handleUrlParams).to.have.been.calledOnce;
|
|
192
|
+
expect(inputAnalysis.handleUrlParams).to.have.been.calledWithMatch({ parsedParams: layer.params }, layer.params);
|
|
192
193
|
});
|
|
193
194
|
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
it('does not call `.handleUrlParams` when match returns false', function () {
|
|
196
|
+
Layer.prototype.match.returns(false);
|
|
196
197
|
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
core.scopes.sources.run({}, () => {
|
|
199
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
200
|
+
});
|
|
199
201
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
+
expect(inputAnalysis.handleUrlParams).not.to.have.been.called;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('does not call `.handleUrlParams` when the route path is undefined', function () {
|
|
206
|
+
core.scopes.sources.run({}, () => {
|
|
207
|
+
Reflect.apply(Layer.prototype.match, { ...layer, route: undefined }, ['/bar']);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
expect(inputAnalysis.handleUrlParams).not.to.have.been.called;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('does not call `.handleUrlParams` when the route path is `*`', function () {
|
|
214
|
+
core.scopes.sources.run({}, () => {
|
|
215
|
+
Reflect.apply(Layer.prototype.match, { ...layer, route: { path: '*' } }, ['/bar']);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(inputAnalysis.handleUrlParams).not.to.have.been.called;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('does not call `.handleUrlParams` when not in context', function () {
|
|
222
|
+
core.scopes.sources.run({}, () => {
|
|
223
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(inputAnalysis.handleUrlParams).not.to.have.been.called;
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('does not call `.handleUrlParams` when no params are present on the current layer', function () {
|
|
230
|
+
layer = { keys: [], params: {} };
|
|
231
|
+
|
|
232
|
+
core.scopes.sources.run({ protect: {} }, () => {
|
|
233
|
+
Reflect.apply(Layer.prototype.match, layer, ['/bar']);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
expect(inputAnalysis.handleUrlParams).not.to.have.been.called;
|
|
202
237
|
});
|
|
203
238
|
|
|
204
|
-
expect(inputAnalysis.handleUrlParams).not.to.have.been.called;
|
|
205
|
-
expect(core.logger.debug).not.to.have.been.called;
|
|
206
239
|
});
|
|
207
240
|
});
|
|
208
241
|
});
|
|
@@ -27,7 +27,7 @@ module.exports = (core) => {
|
|
|
27
27
|
|
|
28
28
|
// Patch `formidable`
|
|
29
29
|
function install() {
|
|
30
|
-
depHooks.resolve({ name: 'formidable' }, (formidable) => {
|
|
30
|
+
depHooks.resolve({ name: 'formidable', version: '<4' }, (formidable) => {
|
|
31
31
|
formidable.IncomingForm.prototype.parse = patcher.patch(formidable.IncomingForm.prototype.parse, {
|
|
32
32
|
name: 'Formidable.IncomingForm.prototype.parse',
|
|
33
33
|
patchType,
|
|
@@ -13,17 +13,9 @@ describe('protect input-analysis hapi', function () {
|
|
|
13
13
|
store,
|
|
14
14
|
inputAnalysis;
|
|
15
15
|
|
|
16
|
-
const Hapi = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
};
|
|
20
|
-
const HapiHapi = {
|
|
21
|
-
name: '@hapi/hapi',
|
|
22
|
-
version: '>=18 <22'
|
|
23
|
-
};
|
|
24
|
-
const HapiPez = {
|
|
25
|
-
name: '@hapi/pez'
|
|
26
|
-
};
|
|
16
|
+
const Hapi = { name: 'hapi' };
|
|
17
|
+
const HapiHapi = { name: '@hapi/hapi' };
|
|
18
|
+
const HapiPez = { name: '@hapi/pez' };
|
|
27
19
|
|
|
28
20
|
beforeEach(function () {
|
|
29
21
|
core = mocks.core();
|
|
@@ -53,9 +45,9 @@ describe('protect input-analysis hapi', function () {
|
|
|
53
45
|
HapiPez.Dispenser = function () { };
|
|
54
46
|
HapiPez.Dispenser.prototype.emit = function () { };
|
|
55
47
|
|
|
56
|
-
core.depHooks.resolve.withArgs({ name: Hapi.name
|
|
57
|
-
core.depHooks.resolve.withArgs({ name: HapiHapi.name
|
|
58
|
-
core.depHooks.resolve.withArgs({ name: HapiPez.name }).yields(HapiPez);
|
|
48
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: Hapi.name })).yields(Hapi);
|
|
49
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: HapiHapi.name })).yields(HapiHapi);
|
|
50
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: HapiPez.name })).yields(HapiPez);
|
|
59
51
|
|
|
60
52
|
hapiSources = require('./hapi')(core);
|
|
61
53
|
hapiSources.install();
|
|
@@ -27,7 +27,7 @@ module.exports = (core) => {
|
|
|
27
27
|
|
|
28
28
|
// Patch `koa-body` package
|
|
29
29
|
function install() {
|
|
30
|
-
depHooks.resolve({ name: 'koa-body' }, (koaBody) => patcher.patch(koaBody, {
|
|
30
|
+
depHooks.resolve({ name: 'koa-body', version: '<7' }, (koaBody) => patcher.patch(koaBody, {
|
|
31
31
|
name: 'koa-body',
|
|
32
32
|
patchType,
|
|
33
33
|
post(data) {
|
|
@@ -27,7 +27,7 @@ module.exports = (core) => {
|
|
|
27
27
|
|
|
28
28
|
// Patch `koa-bodyparser` package
|
|
29
29
|
function install() {
|
|
30
|
-
depHooks.resolve({ name: 'koa-bodyparser' }, (koaBodyparser) => patcher.patch(koaBodyparser, {
|
|
30
|
+
depHooks.resolve({ name: 'koa-bodyparser', version: '<5' }, (koaBodyparser) => patcher.patch(koaBodyparser, {
|
|
31
31
|
name: 'koa-bodyparser',
|
|
32
32
|
patchType,
|
|
33
33
|
post(data) {
|
|
@@ -34,7 +34,7 @@ module.exports = (core) => {
|
|
|
34
34
|
* registers a depHook for koa module instrumentation
|
|
35
35
|
*/
|
|
36
36
|
function install() {
|
|
37
|
-
depHooks.resolve({ name: 'koa', version: '>=2.3.0' }, (Koa) => {
|
|
37
|
+
depHooks.resolve({ name: 'koa', version: '>=2.3.0 <3' }, (Koa) => {
|
|
38
38
|
function contrastStartMiddleware(ctx, next) {
|
|
39
39
|
if (ctx.query && Object.keys(ctx.query).length) {
|
|
40
40
|
const sourceContext = protect.getSourceContext();
|
|
@@ -65,15 +65,15 @@ module.exports = (core) => {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
// Patch `koa-router` and `@koa/router` to handle parsed params
|
|
68
|
-
['koa-router', '@koa/router'].forEach(router => {
|
|
68
|
+
[['koa-router', '<14'], ['@koa/router', '<14']].forEach(([router, version]) => {
|
|
69
69
|
depHooks.resolve(
|
|
70
|
-
{ name: router, file: 'lib/layer.js' },
|
|
70
|
+
{ name: router, version, file: 'lib/layer.js' },
|
|
71
71
|
(layer) => {
|
|
72
72
|
layer.prototype = patcher.patch(layer.prototype, 'params', {
|
|
73
73
|
name: `[${router}].layer.prototype`,
|
|
74
74
|
patchType,
|
|
75
75
|
post({ result }) {
|
|
76
|
-
const sourceContext = protect.getSourceContext(
|
|
76
|
+
const sourceContext = protect.getSourceContext();
|
|
77
77
|
|
|
78
78
|
if (sourceContext && Object.keys(result).length) {
|
|
79
79
|
sourceContext.parsedParams = result;
|
|
@@ -87,7 +87,7 @@ module.exports = (core) => {
|
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
// Patch `koa-cookie`
|
|
90
|
-
depHooks.resolve({ name: 'koa-cookie' }, (koaCookie) => {
|
|
90
|
+
depHooks.resolve({ name: 'koa-cookie', version: '<2' }, (koaCookie) => {
|
|
91
91
|
const { default: cookieParser } = koaCookie;
|
|
92
92
|
koaCookie.default = patcher.patch(cookieParser, {
|
|
93
93
|
name: 'koa-cookie',
|
|
@@ -30,7 +30,7 @@ module.exports = (core) => {
|
|
|
30
30
|
|
|
31
31
|
// Patch `multer`
|
|
32
32
|
function install() {
|
|
33
|
-
depHooks.resolve({ name: 'multer', file: 'lib/make-middleware.js' }, (multerMakeMiddleware) => patcher.patch(multerMakeMiddleware, {
|
|
33
|
+
depHooks.resolve({ name: 'multer', version: '<2', file: 'lib/make-middleware.js' }, (multerMakeMiddleware) => patcher.patch(multerMakeMiddleware, {
|
|
34
34
|
name: 'multer.make-middleware',
|
|
35
35
|
patchType,
|
|
36
36
|
post(data) {
|
|
@@ -25,7 +25,7 @@ module.exports = function init(core) {
|
|
|
25
25
|
return inputAnalysis.restifyInstrumentation = {
|
|
26
26
|
install() {
|
|
27
27
|
depHooks.resolve(
|
|
28
|
-
{ name: 'restify', file: 'lib/server.js', version: '>=8' },
|
|
28
|
+
{ name: 'restify', file: 'lib/server.js', version: '>=8 <12' },
|
|
29
29
|
(Server) => {
|
|
30
30
|
patcher.patch(Server.prototype, '_afterUse', {
|
|
31
31
|
name: 'restify.Server.prototype._afterUse',
|
|
@@ -22,7 +22,7 @@ describe('protect input-analysis restify v8+', function () {
|
|
|
22
22
|
req = {};
|
|
23
23
|
|
|
24
24
|
core.depHooks.resolve
|
|
25
|
-
.withArgs({ name: 'restify', file: 'lib/server.js', version: '>=8' })
|
|
25
|
+
.withArgs({ name: 'restify', file: 'lib/server.js', version: '>=8 <12' })
|
|
26
26
|
.yields(Server);
|
|
27
27
|
|
|
28
28
|
inputAnalysis.restifyInstrumentation.install();
|
|
@@ -27,7 +27,7 @@ module.exports = (core) => {
|
|
|
27
27
|
|
|
28
28
|
// Patch `universal-cookie` package
|
|
29
29
|
function install() {
|
|
30
|
-
depHooks.resolve({ name: 'universal-cookie', file: 'cjs/utils.js' }, (uCookieUtils) => patcher.patch(uCookieUtils, 'parseCookies', {
|
|
30
|
+
depHooks.resolve({ name: 'universal-cookie', version: '<8', file: 'cjs/utils.js' }, (uCookieUtils) => patcher.patch(uCookieUtils, 'parseCookies', {
|
|
31
31
|
name: 'universal-cookie.utils',
|
|
32
32
|
patchType,
|
|
33
33
|
post({ result }) {
|
|
@@ -49,7 +49,7 @@ module.exports = function (core) {
|
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
function install() {
|
|
52
|
-
depHooks.resolve({ name: 'child_process' }, cp => {
|
|
52
|
+
depHooks.resolve({ name: 'child_process', version: '*' }, cp => {
|
|
53
53
|
['exec', 'execSync'].forEach((method) => {
|
|
54
54
|
const name = `child_process.${method}`;
|
|
55
55
|
patcher.patch(cp, method, {
|
|
@@ -65,7 +65,7 @@ module.exports = function init(core) {
|
|
|
65
65
|
|
|
66
66
|
return core.protect.inputTracing.fsInstrumentation = {
|
|
67
67
|
install() {
|
|
68
|
-
depHooks.resolve({ name: 'fs' }, (fs) => {
|
|
68
|
+
depHooks.resolve({ name: 'fs', version: '*' }, (fs) => {
|
|
69
69
|
for (const method of FS_METHODS) {
|
|
70
70
|
// not all methods are available on every OS or Node version.
|
|
71
71
|
if (fs[method.name]) {
|
|
@@ -97,7 +97,7 @@ module.exports = function init(core) {
|
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
depHooks.resolve({ name: 'fs/promises' }, (fsPromises) => {
|
|
100
|
+
depHooks.resolve({ name: 'fs/promises', version: '*' }, (fsPromises) => {
|
|
101
101
|
for (const method of FS_METHODS) {
|
|
102
102
|
if (method.promises && fsPromises[method.name]) {
|
|
103
103
|
patcher.patch(fsPromises, method.name, {
|
|
@@ -30,8 +30,8 @@ describe('protect input-tracing fs', function () {
|
|
|
30
30
|
core = mocks.core();
|
|
31
31
|
core.logger = mocks.logger();
|
|
32
32
|
core.depHooks = mocks.depHooks();
|
|
33
|
-
core.depHooks.resolve.withArgs({ name: 'fs' }).yields(fs);
|
|
34
|
-
core.depHooks.resolve.withArgs({ name: 'fs/promises' }).yields(fsPromises);
|
|
33
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: 'fs' })).yields(fs);
|
|
34
|
+
core.depHooks.resolve.withArgs(sinon.match({ name: 'fs/promises' })).yields(fsPromises);
|
|
35
35
|
core.scopes = mocks.scopes();
|
|
36
36
|
sinon.stub(core.scopes.sources, 'getStore').returns(store);
|
|
37
37
|
core.patcher = patcher(core);
|
|
@@ -27,7 +27,7 @@ module.exports = function(core) {
|
|
|
27
27
|
} = core;
|
|
28
28
|
|
|
29
29
|
function install() {
|
|
30
|
-
depHooks.resolve({ name: 'http' }, http => {
|
|
30
|
+
depHooks.resolve({ name: 'http', version: '*' }, http => {
|
|
31
31
|
for (const method of ['write', 'end']) {
|
|
32
32
|
const name = `http.ServerResponse.prototype.${method}`;
|
|
33
33
|
patcher.patch(http.ServerResponse.prototype, method, {
|
|
@@ -36,7 +36,7 @@ module.exports = function(core) {
|
|
|
36
36
|
pre(data) {
|
|
37
37
|
if (instrumentation.isLocked()) return;
|
|
38
38
|
|
|
39
|
-
const sourceContext = protect.getSourceContext(
|
|
39
|
+
const sourceContext = protect.getSourceContext();
|
|
40
40
|
if (!sourceContext) return;
|
|
41
41
|
|
|
42
42
|
const value = data.args[0]?.toString?.();
|
|
@@ -27,7 +27,7 @@ module.exports = function(core) {
|
|
|
27
27
|
} = core;
|
|
28
28
|
|
|
29
29
|
function install() {
|
|
30
|
-
depHooks.resolve({ name: 'http2' }, http2 => {
|
|
30
|
+
depHooks.resolve({ name: 'http2', version: '*' }, http2 => {
|
|
31
31
|
for (const method of ['write', 'end']) {
|
|
32
32
|
const name = `http2.Http2ServerResponse.prototype.${method}`;
|
|
33
33
|
patcher.patch(http2.Http2ServerResponse.prototype, method, {
|
|
@@ -36,7 +36,7 @@ module.exports = function(core) {
|
|
|
36
36
|
pre(data) {
|
|
37
37
|
if (instrumentation.isLocked()) return;
|
|
38
38
|
|
|
39
|
-
const sourceContext = protect.getSourceContext(
|
|
39
|
+
const sourceContext = protect.getSourceContext();
|
|
40
40
|
|
|
41
41
|
if (!sourceContext) return;
|
|
42
42
|
|
|
@@ -43,7 +43,7 @@ module.exports = function(core) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function install() {
|
|
46
|
-
depHooks.resolve({ name: 'marsdb' }, marsdb => {
|
|
46
|
+
depHooks.resolve({ name: 'marsdb', version: '<1' }, marsdb => {
|
|
47
47
|
methods.forEach((method) => {
|
|
48
48
|
const name = `marsdb.Collection.prototype.${method}`;
|
|
49
49
|
|
|
@@ -52,7 +52,7 @@ module.exports = function(core) {
|
|
|
52
52
|
patchType,
|
|
53
53
|
pre({ args, hooked, orig }) {
|
|
54
54
|
const value = getCursorQueryData(args);
|
|
55
|
-
const sourceContext = getSourceContext(
|
|
55
|
+
const sourceContext = getSourceContext();
|
|
56
56
|
|
|
57
57
|
if (
|
|
58
58
|
!sourceContext ||
|
|
@@ -34,7 +34,7 @@ describe('protect input-tracing marsdb', function () {
|
|
|
34
34
|
mockMarsDb.Collection.prototype[method] = () => { };
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
core.depHooks.resolve.
|
|
37
|
+
core.depHooks.resolve.yields(mockMarsDb);
|
|
38
38
|
|
|
39
39
|
marsdbInstr = require('./marsdb')(core);
|
|
40
40
|
});
|
|
@@ -142,7 +142,7 @@ module.exports = function(core) {
|
|
|
142
142
|
const argsIdxsToCheck = vulnerableArgIdxs || [0];
|
|
143
143
|
return function(next, data) {
|
|
144
144
|
const { args, name, hooked, orig } = data;
|
|
145
|
-
const sourceCtx = getSourceContext(
|
|
145
|
+
const sourceCtx = getSourceContext();
|
|
146
146
|
|
|
147
147
|
if (instrumentation.isLocked() || !sourceCtx) {
|
|
148
148
|
return next();
|
|
@@ -158,7 +158,7 @@ module.exports = function(core) {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
instr.install = function() {
|
|
161
|
-
depHooks.resolve({ name: 'mongodb' }, (mongodb, version) => {
|
|
161
|
+
depHooks.resolve({ name: 'mongodb', version: '<7' }, (mongodb, version) => {
|
|
162
162
|
patchCollection(mongodb, version);
|
|
163
163
|
patchDatabase(mongodb, version);
|
|
164
164
|
});
|
|
@@ -39,9 +39,7 @@ describe('protect input-tracing mongodb', function() {
|
|
|
39
39
|
({ core, simulateRequestScope } = initProtectFixture());
|
|
40
40
|
require('../../get-source-context')(core);
|
|
41
41
|
|
|
42
|
-
core.depHooks.resolve
|
|
43
|
-
.withArgs({ name: 'mongodb' })
|
|
44
|
-
.yields({ Collection, Db });
|
|
42
|
+
core.depHooks.resolve.yields({ Collection, Db });
|
|
45
43
|
|
|
46
44
|
instr = require('./mongodb')(core);
|
|
47
45
|
instr.install();
|
|
@@ -247,7 +245,7 @@ describe('protect input-tracing mongodb', function() {
|
|
|
247
245
|
command() { }
|
|
248
246
|
}
|
|
249
247
|
core.depHooks.resolve
|
|
250
|
-
.withArgs({ name: 'mongodb' })
|
|
248
|
+
.withArgs(sinon.match({ name: 'mongodb' }))
|
|
251
249
|
.yields({ Collection, Db }, 'v5.x.x');
|
|
252
250
|
|
|
253
251
|
const instr = require('./mongodb')(core);
|