@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
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@contrast/protect",
3
- "version": "1.53.1",
3
+ "version": "1.54.1",
4
4
  "description": "Contrast service providing framework-agnostic Protect support",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
7
7
  "files": [
8
- "lib/"
8
+ "lib/",
9
+ "!*.test.*",
10
+ "!tsconfig.*",
11
+ "!*.map"
9
12
  ],
10
13
  "main": "lib/index.js",
11
14
  "types": "lib/index.d.ts",
@@ -17,17 +20,17 @@
17
20
  "test": "../scripts/test.sh"
18
21
  },
19
22
  "dependencies": {
20
- "@contrast/agent-lib": "^7.0.1",
23
+ "@contrast/agent-lib": "^9.0.0",
21
24
  "@contrast/common": "1.29.1",
22
- "@contrast/config": "1.40.1",
23
- "@contrast/core": "1.45.1",
24
- "@contrast/dep-hooks": "1.14.1",
25
- "@contrast/esm-hooks": "2.19.1",
26
- "@contrast/instrumentation": "1.24.1",
27
- "@contrast/logger": "1.18.1",
28
- "@contrast/patcher": "1.17.1",
29
- "@contrast/rewriter": "1.21.1",
30
- "@contrast/scopes": "1.15.1",
25
+ "@contrast/config": "1.40.2",
26
+ "@contrast/core": "1.45.2",
27
+ "@contrast/dep-hooks": "1.14.2",
28
+ "@contrast/esm-hooks": "2.19.3",
29
+ "@contrast/instrumentation": "1.24.2",
30
+ "@contrast/logger": "1.18.2",
31
+ "@contrast/patcher": "1.17.2",
32
+ "@contrast/rewriter": "1.21.3",
33
+ "@contrast/scopes": "1.15.2",
31
34
  "async-hook-domain": "^4.0.1",
32
35
  "ipaddr.js": "^2.0.1",
33
36
  "on-finished": "^2.4.1",
@@ -1,52 +0,0 @@
1
- 'use strict';
2
-
3
- const { expect } = require('chai');
4
- const { initProtectFixture, createProtectStore } = require('@contrast/test/fixtures');
5
- const SecurityException = require('../security-exception');
6
-
7
- describe('protect error-handlers common-handler', function () {
8
- let core, simulateRequestScope, commonHandler;
9
-
10
- beforeEach(function () {
11
- ({
12
- core,
13
- simulateRequestScope
14
- } = initProtectFixture());
15
-
16
- commonHandler = core.protect.errorHandlers.commonHandler;
17
- });
18
-
19
- it('should re-throw if not security excpetion', function () {
20
- simulateRequestScope(() => {
21
- const err = new Error('Not a SecurityException');
22
- expect(() => {
23
- commonHandler(err);
24
- }).to.throw(err);
25
- });
26
- });
27
-
28
- it('should catch exception and delegate to source context to block', function () {
29
- const customStore = { protect: createProtectStore() };
30
- customStore.protect.securityException = ['block', 'cmd-injection'];
31
-
32
- simulateRequestScope(() => {
33
- expect(() => {
34
- commonHandler(new SecurityException());
35
- expect(customStore.protect.block).to.have.been.calledWith('block', 'cmd-injection');
36
- }).not.to.throw();
37
- }, customStore);
38
- });
39
-
40
- it('should catch exception if request context is unavailable but will log and NOT block', function () {
41
- const customStore = { protect: createProtectStore() };
42
- customStore.protect.securityException = ['block', 'cmd-injection'];
43
-
44
- expect(() => {
45
- commonHandler(new SecurityException());
46
- expect(customStore.protect.block).to.not.have.been.called;
47
- expect(core.logger.info).to.have.been.calledWith(
48
- 'SecurityException caught by Contrast but Protect store is unavailable for req handling'
49
- );
50
- }).not.to.throw();
51
- });
52
- });
@@ -1,32 +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 error-handlers', function () {
8
- let core, errorHandlers;
9
-
10
- const installerList = [
11
- 'expressErrorHandler',
12
- 'fastifyErrorHandler',
13
- 'hapiErrorHandler',
14
- 'koa2ErrorHandler',
15
- 'restifyErrorHandler'
16
- ];
17
-
18
- beforeEach(function () {
19
- ({ core } = initProtectFixture());
20
- errorHandlers = core.protect.errorHandlers;
21
- installerList.forEach((installer) => {
22
- sinon.stub(errorHandlers[installer], 'install');
23
- });
24
- });
25
-
26
- it('installs subcomponents', function () {
27
- errorHandlers.install();
28
- installerList.forEach((installer) => {
29
- expect(errorHandlers[installer].install).to.have.been.called;
30
- });
31
- });
32
- });
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- const { expect } = require('chai');
4
- const sinon = require('sinon');
5
- const { initProtectFixture } = require('@contrast/test/fixtures');
6
-
7
- describe('protect error-handlers init-domain', function () {
8
- let core;
9
-
10
- beforeEach(function () {
11
- ({ core } = initProtectFixture());
12
-
13
- sinon.stub(core.protect.errorHandlers, 'commonHandler');
14
- });
15
-
16
- describe('domain integration', function () {
17
- it('instantiates async-hook-domain with common error handler', function () {
18
- const d = core.protect.errorHandlers.initDomain();
19
- expect(d.onerror).to.equal(core.protect.errorHandlers.commonHandler);
20
- });
21
- });
22
- });
@@ -1,290 +0,0 @@
1
- /* eslint-disable */
2
- 'use strict';
3
-
4
- const sinon = require('sinon');
5
- const { expect } = require('chai');
6
- const scopes = require('@contrast/scopes');
7
- const patcher = require('@contrast/patcher');
8
- const mocks = require('@contrast/test/mocks');
9
- const SecurityException = require('../../security-exception');
10
-
11
- describe('protect error-handlers express', function () {
12
- let core, store, errorHandlerInstr;
13
-
14
- const throwingHandler = (error) => async function () {
15
- await Promise.reject(error);
16
- };
17
-
18
- beforeEach(function () {
19
- core = mocks.core();
20
- core.config = mocks.config();
21
- core.logger = mocks.logger();
22
- core.scopes = scopes(core);
23
- core.protect = mocks.protect();
24
- require('../../get-source-context')(core);
25
- core.depHooks = mocks.depHooks();
26
- core.patcher = patcher(core);
27
-
28
- store = {
29
- protect: {
30
- block: sinon.stub(),
31
- securityException: ['block', 'cmd-injection']
32
- }
33
- };
34
-
35
- sinon.spy(core.patcher, 'patch');
36
- });
37
-
38
- describe('finalhandler', function () {
39
- let finalhandler, returnedFn;
40
-
41
- beforeEach(function () {
42
- finalhandler = function () {
43
- return function () { };
44
- };
45
-
46
- core.depHooks.resolve.withArgs({ name: 'finalhandler', version: '<3' }).yields(finalhandler);
47
-
48
- errorHandlerInstr = require('./express')(core);
49
- errorHandlerInstr.install();
50
-
51
- const patchedFinalhandler = core.patcher.patch.getCall(0).returnValue;
52
- returnedFn = patchedFinalhandler();
53
- });
54
-
55
- it('should block the request when there is SecurityException', function () {
56
- const error = SecurityException.create();
57
-
58
- core.scopes.sources.run(store, () => {
59
- returnedFn(error);
60
- expect(core.logger.info).not.to.have.been.called;
61
- expect(store.protect.block).to.have.been.calledWith('block', 'cmd-injection');
62
- });
63
- });
64
-
65
- it('should not block the request when there is SecurityException but sourceContext is missing', function () {
66
- const error = SecurityException.create();
67
-
68
- core.scopes.sources.run({}, () => {
69
- returnedFn(error);
70
- expect(core.logger.info).to.have.been.calledWith(
71
- { funcKey: 'protect-error-handling:finalHandler.returnedFunction' },
72
- 'source context not found; unable to handle response',
73
- );
74
- });
75
- });
76
-
77
- it('should skip the instrumentation when there is no SecurityException', function () {
78
- const error = new Error('Error');
79
-
80
- core.scopes.sources.run({}, () => {
81
- returnedFn(error);
82
- expect(core.logger.info).not.to.have.been.called;
83
- expect(store.protect.block).not.to.have.been.called;
84
- });
85
- });
86
- });
87
-
88
- [
89
- { name: 'express', version: '4', file: 'lib/router/layer.js' },
90
- { name: 'router', version: '2', file: 'lib/layer.js' }
91
- ].forEach((args) => {
92
- const fn = args.name === 'express' ? 'handle_error' : 'handleError';
93
- describe(`${args.name} Layer.prototype.${fn}`, function () {
94
- let Layer;
95
-
96
- beforeEach(function () {
97
- Layer = function () { };
98
-
99
- Layer.prototype[fn] = function () { };
100
-
101
- core.depHooks.resolve.withArgs(args).yields(Layer);
102
-
103
- errorHandlerInstr = require('./express')(core);
104
- errorHandlerInstr.install();
105
- });
106
-
107
- it('should block the request when there is SecurityException', function () {
108
- const error = SecurityException.create();
109
-
110
- core.scopes.sources.run(store, () => {
111
- Layer.prototype[fn](error);
112
- expect(core.logger.info).not.to.have.been.called;
113
- expect(store.protect.block).to.have.been.calledWith('block', 'cmd-injection');
114
- });
115
- });
116
-
117
- it('should not block the request when there is SecurityException but sourceContext is missing', function () {
118
- const error = SecurityException.create();
119
-
120
- core.scopes.sources.run({}, () => {
121
- Layer.prototype[fn](error);
122
- expect(core.logger.info).to.have.been.calledWith(
123
- { funcKey: `protect-error-handling:Layer.prototype.${fn}` },
124
- 'source context not found; unable to handle response'
125
- );
126
- });
127
- });
128
-
129
- it('should skip the instrumentation when there is no SecurityException', function () {
130
- const error = new Error('Error');
131
-
132
- core.scopes.sources.run({}, () => {
133
- Layer.prototype[fn](error);
134
- expect(core.logger.info).not.to.have.been.called;
135
- expect(store.protect.block).not.to.have.been.called;
136
- });
137
- });
138
- });
139
-
140
- describe(`${args.name} Layer handle`, function () {
141
- let Layer, patchedLayer;
142
- const error = SecurityException.create();
143
- const fn = throwingHandler(error);
144
- beforeEach(function () {
145
- Layer = function () {
146
- return {
147
- handle: fn
148
- }
149
- };
150
-
151
- errorHandlerInstr = require('./express')(core);
152
- errorHandlerInstr.install();
153
- [patchedLayer] = core.depHooks.resolve.withArgs(args).yield(Layer);
154
- });
155
-
156
- it('should block the request when there is SecurityException', async function () {
157
- await core.scopes.sources.run(store, async () => {
158
- await patchedLayer().handle();
159
- });
160
- expect(core.logger.info).not.to.have.been.called;
161
- expect(store.protect.block).to.have.been.calledWith('block', 'cmd-injection');
162
- });
163
-
164
- it('should not block the request when there is SecurityException but sourceContext is missing', async function () {
165
- await core.scopes.sources.run({}, async () => {
166
- await patchedLayer().handle();
167
- });
168
-
169
- expect(core.logger.info).to.have.been.calledWith(
170
- { funcKey: 'protect-error-handling:handle' },
171
- 'source context not found; unable to handle response',
172
- );
173
- });
174
-
175
- it('should skip the instrumentation when there is no SecurityException', async function () {
176
- const error = new Error('Error');
177
- const fn = throwingHandler(error);
178
- Layer = function () {
179
- return {
180
- handle: fn
181
- }
182
- };
183
-
184
- errorHandlerInstr = require('./express')(core);
185
- errorHandlerInstr.install();
186
- [patchedLayer] = core.depHooks.resolve.withArgs(args).yield(Layer);
187
-
188
- try {
189
- await core.scopes.sources.run(store, async () => {
190
- await patchedLayer().handle();
191
- });
192
- } catch (err) {
193
- expect(err).to.equal(error);
194
- expect(core.logger.info).not.to.have.been.called;
195
- expect(store.protect.block).not.to.have.been.called;
196
- }
197
- });
198
- });
199
- });
200
-
201
- [
202
- { name: 'express', version: '4', file: 'lib/router/index.js' },
203
- { name: 'router', version: '2' }
204
- ].forEach((args) => {
205
- describe(`${args.name} Router param`, function () {
206
- let Router, param;
207
- const sampleFn = function () { };
208
-
209
- beforeEach(function () {
210
-
211
- Router = function() { };
212
- if (args.name === 'express') {
213
- Router.prototype.constructor = {
214
- param: function () { },
215
- };
216
- param = (...args) => Router.prototype.constructor.param(...args);
217
- } else {
218
- Router.prototype = {
219
- param: function () { },
220
- };
221
- param = (...args) => Router.prototype.param(...args);
222
- }
223
- core.depHooks.resolve.withArgs(args).yields(Router);
224
-
225
- core.patcher.patch.resetHistory();
226
-
227
- errorHandlerInstr = require('./express')(core);
228
- errorHandlerInstr.install();
229
- });
230
-
231
- it('should patch the function for the param property', function () {
232
- param('sampleFn', sampleFn);
233
- expect(core.patcher.patch).to.have.been.calledWith(sinon.match.array, '1', sinon.match.object);
234
- });
235
-
236
- it('should block the request when there is SecurityException', async function () {
237
- const error = SecurityException.create();
238
- const fn = throwingHandler(error);
239
-
240
- param('fn', fn);
241
-
242
- const patchedFn = core.patcher.patch.getCall(1).returnValue[1];
243
-
244
- await core.scopes.sources.run(store, async () => {
245
- await patchedFn();
246
- });
247
-
248
- expect(core.logger.info).not.to.have.been.called;
249
- expect(store.protect.block).to.have.been.calledWith('block', 'cmd-injection');
250
- });
251
-
252
- it('should not block the request when there is SecurityException but sourceContext is missing', async function () {
253
- const error = SecurityException.create();
254
- const fn = throwingHandler(error);
255
-
256
- param('fn', fn);
257
-
258
- const patchedFn = core.patcher.patch.getCall(1).returnValue[1];
259
-
260
- await core.scopes.sources.run({}, async () => {
261
- await patchedFn();
262
- });
263
-
264
- expect(core.logger.info).to.have.been.calledWith(
265
- { funcKey: 'protect-error-handling:express.route-handler' },
266
- 'source context not found; unable to handle response',
267
- );
268
- });
269
-
270
- it('should skip the instrumentation when there is no SecurityException', async function () {
271
- const error = new Error('Error');
272
- const fn = throwingHandler(error);
273
-
274
- param('fn', fn);
275
-
276
- const patchedFn = core.patcher.patch.getCall(1).returnValue[1];
277
-
278
- try {
279
- await core.scopes.sources.run(store, async () => {
280
- await patchedFn();
281
- });
282
- } catch (err) {
283
- expect(err).to.equal(error);
284
- expect(core.logger.info).not.to.have.been.called;
285
- expect(store.protect.block).not.to.have.been.called;
286
- }
287
- });
288
- });
289
- });
290
- });
@@ -1,130 +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 securityException = require('../../security-exception');
9
-
10
- describe('protect error-handlers fastify', function () {
11
- let core, errorHandler, fastify, server, reply;
12
-
13
- beforeEach(function () {
14
- core = mocks.core();
15
- core.config = mocks.config();
16
- core.logger = mocks.logger();
17
- core.scopes = scopes(core);
18
- core.protect = mocks.protect();
19
- require('../../get-source-context')(core);
20
- core.depHooks = mocks.depHooks();
21
- core.patcher = patcher(core);
22
-
23
- server = {
24
- setErrorHandler: sinon.stub(),
25
- errorHandler: sinon.stub()
26
- };
27
- fastify = function () {
28
- return server;
29
- };
30
- core.depHooks.resolve.callsFake((desc, cb) => {
31
- fastify = cb(fastify);
32
- });
33
- reply = {
34
- log: {
35
- info: sinon.stub(),
36
- error: sinon.stub()
37
- },
38
- send: sinon.stub(),
39
- statusCode: 500,
40
- };
41
-
42
- errorHandler = require('./fastify')(core);
43
- sinon.spy(errorHandler, 'defaultErrorHandler');
44
- errorHandler.install();
45
-
46
- fastify();
47
- });
48
-
49
- describe('instrumentation adds custom handler', function () {
50
- it('patches fastify', function () {
51
- expect(server.setErrorHandler).to.have.been.calledWith(errorHandler.handler);
52
- });
53
- });
54
-
55
- describe('defaultErrorHandler()', function () {
56
- let request, err;
57
-
58
- beforeEach(function () {
59
- request = {};
60
- err = {};
61
- });
62
-
63
- it('logs at error level when 500 status code', function () {
64
- errorHandler.handler(err, request, reply);
65
- expect(reply.log.error).to.have.been.calledWith({ req: request, res: reply, err });
66
- });
67
-
68
- it('logs at info level when <500 status code', function () {
69
- reply.statusCode = 404;
70
- errorHandler.handler(err, request, reply);
71
- expect(reply.log.info).to.have.been.calledWith({ res: reply, err });
72
- });
73
- });
74
-
75
- describe('handler()', function () {
76
- let request, err, store, userHandler;
77
-
78
- beforeEach(function () {
79
- request = {};
80
- err = securityException.create();
81
- store = {
82
- protect: {
83
- block: sinon.stub(),
84
- securityException: ['block', 'cmd-injection']
85
- }
86
- };
87
- userHandler = sinon.stub();
88
- });
89
-
90
- it('calls default handler when the source context is not available', function () {
91
- errorHandler.handler(err, request, reply);
92
- });
93
-
94
- it('when set, calls user handler when the source context is not available', function () {
95
- server.setErrorHandler(userHandler);
96
- errorHandler.handler(err, request, reply);
97
- expect(userHandler).to.have.been.calledWith(err, request, reply);
98
- });
99
-
100
- it('calls source context\'s .block() with mode and id of rule which raised error', function () {
101
- const {
102
- protect: {
103
- block,
104
- securityException
105
- }
106
- } = store;
107
- core.scopes.sources.run(store, () => {
108
- errorHandler.handler(err, request, reply);
109
- expect(block).to.have.been.calledWith(...securityException);
110
- });
111
- });
112
-
113
- it('calls default error handler when error is not security exception', function () {
114
- err = {};
115
- core.scopes.sources.run(store, () => {
116
- errorHandler.handler(err, request, reply);
117
- expect(errorHandler.defaultErrorHandler).to.have.been.calledWith(err, request, reply);
118
- });
119
- });
120
-
121
- it('when set, calls user handler when error is ont seecurity exception', function () {
122
- err = {};
123
- server.setErrorHandler(userHandler);
124
- core.scopes.sources.run(store, () => {
125
- errorHandler.handler(err, request, reply);
126
- expect(userHandler).to.have.been.calledWith(err, request, reply);
127
- });
128
- });
129
- });
130
- });
@@ -1,102 +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 SecurityException = require('../../security-exception');
9
-
10
- describe('protect error-handlers hapi', function () {
11
- let core,
12
- errorHandler,
13
- store;
14
-
15
- const Boom = {
16
- name: 'boom',
17
- };
18
- const HapiBoom = {
19
- name: '@hapi/boom'
20
- };
21
-
22
- beforeEach(function () {
23
- core = mocks.core();
24
- core.config = mocks.config();
25
- core.logger = mocks.logger();
26
- core.scopes = scopes(core);
27
- core.protect = mocks.protect();
28
- require('../../get-source-context')(core);
29
- core.depHooks = mocks.depHooks();
30
- core.patcher = patcher(core);
31
-
32
- store = {
33
- protect: {
34
- block: sinon.stub(),
35
- securityException: ['block', 'cmd-injection']
36
- }
37
- };
38
-
39
- Boom.boomify = function boom() { };
40
- HapiBoom.boomify = function hapiBoom() { };
41
-
42
- core.depHooks.resolve.withArgs(sinon.match({ name: Boom.name })).yields(Boom);
43
- core.depHooks.resolve.withArgs(sinon.match({ name: HapiBoom.name })).yields(HapiBoom);
44
-
45
- errorHandler = require('./hapi')(core);
46
- errorHandler.install();
47
- });
48
-
49
- [Boom, HapiBoom].forEach((module) => {
50
- it(`should block the request when there is SecurityException - ${module.name}`, function () {
51
- const { boomify } = module;
52
- const error = SecurityException.create();
53
-
54
- core.scopes.sources.run(store, () => {
55
- error.output = {
56
- statusCode: 500,
57
- };
58
- error.reformat = () => ({});
59
-
60
- boomify(error);
61
- expect(core.logger.info).to.have.been.calledWith(
62
- { funcKey: `protect-error-handling:${module.name}.boomify`, mode: 'block', ruleId: 'cmd-injection' },
63
- 'Request blocked'
64
- );
65
- expect(error.output).to.have.property('statusCode', 403);
66
- });
67
- });
68
- });
69
-
70
- [Boom, HapiBoom].forEach((module) => {
71
- it(`should not block the request when there is SecurityException but sourceContext is missing - ${module.name}`, function () {
72
- const { boomify } = module;
73
- const error = SecurityException.create();
74
-
75
- core.scopes.sources.run({}, () => {
76
- error.output = {
77
- statusCode: 500,
78
- };
79
- error.reformat = () => ({});
80
-
81
- boomify(error);
82
- expect(core.logger.info).to.have.been.calledWith(
83
- { funcKey: `protect-error-handling:${module.name}.boomify` },
84
- 'source context not found; unable to handle response'
85
- );
86
- });
87
- });
88
- });
89
-
90
- [Boom, HapiBoom].forEach((module) => {
91
- it(`should skip the instrumentation when there is no SecurityException - ${module.name}`, function () {
92
- const { boomify } = module;
93
- const error = new Error('Error');
94
-
95
- core.scopes.sources.run({}, () => {
96
- boomify(error);
97
- expect(core.logger.info).not.to.have.been.called;
98
- expect(store.protect.block).not.to.have.been.called;
99
- });
100
- });
101
- });
102
- });