@contrast/protect 1.54.0 → 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 +14 -11
  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 -1237
  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,219 +0,0 @@
1
- 'use strict';
2
-
3
- const sinon = require('sinon');
4
- const { expect } = require('chai');
5
- const { Rule, Event } = require('@contrast/common');
6
- const { initProtectFixture } = require('@contrast/test/fixtures');
7
-
8
- /* eslint-disable newline-per-chained-call */
9
-
10
- describe('protect make-source-context', function () {
11
- let core;
12
-
13
- beforeEach(function () {
14
- ({ core } = initProtectFixture());
15
- core.config.protect.rules = makeProtectRulesConfig('monitor');
16
- });
17
-
18
- describe('makeSourceContext() for policy', function () {
19
- it('builds policy with rulesMask and modes', function () {
20
- require('../../protect')(core);
21
-
22
- const [req, res] = makeReqRes({}, {});
23
- const sc = core.protect.makeSourceContext(req, res);
24
-
25
- expect(sc.block).to.be.a('function');
26
- expect(sc.policy).to.deep.equal({
27
- rulesMask: 511,
28
- exclusions: {
29
- ignoreQuerystring: false,
30
- querystringPolicy: null,
31
- ignoreBody: false,
32
- bodyPolicy: null,
33
- header: [],
34
- cookie: [],
35
- parameter: [],
36
- },
37
- ...Object.values(Rule).reduce((acc, ruleId) => ({ ...acc, [ruleId]: 'monitor' }), {}),
38
- });
39
- expect(sc.exclusions).to.deep.equal([]);
40
- expect(sc.virtualPatchesEvaluators).to.deep.equal([]);
41
- expect(sc.trackRequest).to.equal(false);
42
- expect(sc.securityException).to.be.undefined;
43
- expect(sc.bodyType).to.be.undefined;
44
- expect(sc.resultsMap).to.eql(Object.create(null));
45
- });
46
- });
47
-
48
- describe('makeSourceContext() for req, res', function () {
49
- const ruleId = 'reflected-xss';
50
- const expectedMode = 'monitor';
51
- const expectedRulesMask = 4;
52
-
53
- const tests = [
54
- { desc: 'works with unmodified req', req: {}, res: {} },
55
- { desc: 'handles an uppercase header name', req: { rawHeaders: ['Accept', '*'] }, res: {} },
56
- { desc: 'does not modify a header value', req: { rawHeaders: ['Accept', 'TEXT/HTmL'] }, res: {} },
57
- { desc: 'handles an empty url', req: { url: '' }, res: {} },
58
- { desc: 'handles search params', req: { url: '/mimsy?borogroves' }, res: {} },
59
- { desc: 'handles only search params', req: { url: '?alice' }, res: {} },
60
- { desc: 'detects multipart content-type', req: { rawHeaders: ['Content-type', 'multipart/x-www-form-urlencoded'] }, res: {} },
61
- { desc: 'blocks when headers not sent', req: {}, res: { writeHead: sinon.stub(), end: sinon.stub() } },
62
- { desc: 'blocks when headers sent', req: {}, res: { writeHead: sinon.stub(), end: sinon.stub(), headersSent: true } },
63
- ];
64
-
65
- tests.forEach((t) => {
66
- it(t.desc, function () {
67
- core.config.protect.rules = makeProtectRulesConfig('off');
68
- core.config.protect.rules['reflected-xss'] = { mode: 'monitor' };
69
-
70
- require('../../protect')(core);
71
-
72
- const [req, res] = makeReqRes(t.req, t.res);
73
-
74
- // default to setting headers but not including a content-type
75
- let contentType = '';
76
- if (!t.req.rawHeaders) {
77
- // the test doesn't set the headers so they are the default
78
- contentType = 'application/x-www-form-urlencoded';
79
- } else if (t.req.rawHeaders[t.req.rawHeaders.length - 1].startsWith('multipart')) {
80
- // the test does set the content-type header (inferred)
81
- contentType = t.req.rawHeaders[t.req.rawHeaders.length - 1];
82
- }
83
- const headers = req.rawHeaders.map((h, ix) => ix & 1 ? h : h.toLowerCase());
84
-
85
- // this is what is really being tested.
86
- const sc = core.protect.makeSourceContext(req, res);
87
-
88
-
89
- const expectedReqData = {
90
- method: 'get',
91
- headers,
92
- uriPath: '/',
93
- queries: '',
94
- httpVersion: '1',
95
- ip: '127.1.1.0',
96
- contentType,
97
- };
98
- if (t.req.rawHeaders) {
99
- expectedReqData.headers = t.req.rawHeaders.map((h, i) => {
100
- if (i & 1 && h.startsWith('multipart')) {
101
- expectedReqData.contentType = h;
102
- }
103
- return i & 1 ? h : h.toLowerCase();
104
- });
105
- }
106
- if (t.req.url !== undefined) {
107
- expectedReqData.uriPath = t.req.url;
108
- expectedReqData.queries = '';
109
- const ix = t.req.url.indexOf('?');
110
- if (ix >= 0) {
111
- expectedReqData.uriPath = t.req.url.slice(0, ix);
112
- expectedReqData.queries = t.req.url.slice(ix + 1);
113
- }
114
- }
115
-
116
- // check that req and res make the expected abstract request
117
- expect(sc).property('reqData').to.deep.equal(expectedReqData);
118
-
119
- // if a block test, does it work as expected?
120
- if (t.res.writeHead) {
121
- sc.block('mode', 'reflected-xss');
122
- if (!t.res.headersSent) {
123
- expect(t.res.writeHead.callCount).to.equal(1);
124
- } else {
125
- expect(t.res.writeHead.callCount).to.equal(0);
126
- }
127
- expect(t.res.end.callCount).to.equal(1);
128
- }
129
-
130
- // check constant items
131
- expect(sc.block).to.be.a('function');
132
- expect(sc.policy.rulesMask).to.equal(expectedRulesMask);
133
- expect(sc.policy[ruleId]).to.equal(expectedMode);
134
- expect(sc.exclusions).to.deep.equal([]);
135
- expect(sc.virtualPatchesEvaluators).to.deep.equal([]);
136
-
137
- expect(sc.trackRequest).to.equal(false);
138
- expect(sc.securityException).to.be.undefined;
139
- expect(sc.bodyType).to.be.undefined;
140
- expect(sc.resultsMap).to.eql(Object.create(null));
141
- });
142
- });
143
- });
144
-
145
- describe('handles a case where the returned policy is null so the request is allowed', function () {
146
- beforeEach(function () {
147
- require('../../protect')(core);
148
- const exclusionDtm = {
149
- urls: [
150
- '.*'
151
- ],
152
- matchStrategy: 'ONLY',
153
- protect_rules: [],
154
- modes: [
155
- 'defend'
156
- ],
157
- name: 'UrlExclusionAllRules'
158
- };
159
-
160
- core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
161
- exclusions: {
162
- input: [],
163
- url: [exclusionDtm]
164
- }
165
- });
166
- });
167
-
168
- it('returns an sourceContext with only allowed property set to true', function () {
169
- const sc = core.protect.makeSourceContext(...makeReqRes());
170
-
171
- expect(sc).to.deep.equal({ allowed: true });
172
- });
173
- });
174
- });
175
-
176
- //
177
- // make a req and res pair
178
- //
179
- function makeReqRes(req = {}, res = {}) {
180
- const defaultReq = {
181
- method: 'get',
182
- url: '/',
183
- httpVersion: '1',
184
- socket: {
185
- remoteAddress: '127.1.1.0'
186
- },
187
- rawHeaders: getRawHeaders(),
188
- };
189
-
190
- const defaultRes = {
191
- headersSent: false,
192
- writeHead() { },
193
- end() { },
194
- };
195
-
196
- return [
197
- Object.assign({}, defaultReq, req),
198
- Object.assign({}, defaultRes, res),
199
- ];
200
- }
201
-
202
- function getRawHeaders() {
203
- return [
204
- 'accept', 'text/html',
205
- 'accept-encoding', 'gzip, deflate, br',
206
- 'user-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.',
207
- 'content-type', 'application/x-www-form-urlencoded'
208
- ];
209
- }
210
-
211
- //
212
- // create the config for protect's rules
213
- //
214
- function makeProtectRulesConfig(mode = 'monitor') {
215
- return Object.values(Rule).reduce((acc, ruleId) => ({
216
- ...acc,
217
- [ruleId]: { mode }
218
- }), { disabled_rules: [] });
219
- }
@@ -1,446 +0,0 @@
1
- 'use strict';
2
-
3
- const { expect } = require('chai');
4
- const sinon = require('sinon');
5
- const {
6
- ConfigSource: { ENVIRONMENT_VARIABLE }, ConfigSource
7
- } = require('@contrast/config');
8
- const { Rule, Event } = require('@contrast/common');
9
- const { initProtectFixture } = require('@contrast/test/fixtures');
10
- const mocks = require('@contrast/test/mocks');
11
- const exclusionSettingsMessage = require('@contrast/test/data/server-settings/exclusions.json');
12
- const policyFactory = require('./policy');
13
-
14
- describe('protect policy', function () {
15
- let core;
16
-
17
- beforeEach(function () {
18
- [
19
- ['cmd-injection', 'block'],
20
- ['path-traversal', 'off'],
21
- ['reflected-xss', 'block_at_perimeter'],
22
- ['sql-injection', 'monitor'],
23
- ].forEach(([ruleId, mode]) => {
24
- process.env[`CONTRAST__PROTECT__RULES__${ruleId.toUpperCase().replace('-', '_')}__MODE`] = mode;
25
- });
26
-
27
- ({ core } = initProtectFixture());
28
- [
29
- ['cmd-injection', 'block'],
30
- ['path-traversal', 'off'],
31
- ['reflected-xss', 'block_at_perimeter'],
32
- ['sql-injection', 'monitor'],
33
- ].forEach(([ruleId, mode]) => {
34
- const name = `protect.rules.${ruleId.replace('-', '_')}.mode`;
35
- core.config.setValue(name, mode, ENVIRONMENT_VARIABLE);
36
- });
37
-
38
- core.protect = mocks.protect();
39
- });
40
-
41
- describe('initialzation and updates', function () {
42
- beforeEach(function () {
43
- core.config.protect.rules.disabled_rules = ['sql-injection'];
44
- [
45
- ['cmd-injection', 'block'],
46
- ['path-traversal', 'off'],
47
- ['reflected-xss', 'block_at_perimeter'],
48
- ['sql-injection', 'monitor'],
49
- ].forEach(([ruleId, mode]) => {
50
- core.config.setValue(`protect.rules.${ruleId}.mode`, mode, ENVIRONMENT_VARIABLE);
51
- });
52
-
53
- policyFactory(core);
54
- });
55
-
56
- it('initializes policy from configuration', function () {
57
- const policy = core.protect.getPolicy();
58
-
59
- expect(policy).to.deep.include({
60
- rulesMask: 20,
61
- 'bot-blocker': 'off',
62
- 'cmd-injection': 'block',
63
- 'cmd-injection-command-backdoors': 'off',
64
- 'cmd-injection-semantic-chained-commands': 'off',
65
- 'cmd-injection-semantic-dangerous-paths': 'off',
66
- 'ip-denylist': 'off',
67
- 'method-tampering': 'off',
68
- 'nosql-injection': 'off',
69
- 'nosql-injection-mongo': 'off',
70
- 'path-traversal': 'off',
71
- 'path-traversal-semantic-file-security-bypass': 'off',
72
- 'reflected-xss': 'block_at_perimeter',
73
- 'sql-injection': 'off',
74
- 'ssjs-injection': 'off',
75
- 'ssrf': 'off',
76
- 'unsafe-code-execution': 'off',
77
- 'unsafe-file-upload': 'off',
78
- 'untrusted-deserialization': 'off',
79
- 'unvalidated-redirect': 'off',
80
- 'virtual-patch': 'off',
81
- 'xxe': 'off',
82
- exclusions: {
83
- bodyPolicy: null,
84
- cookie: [],
85
- header: [],
86
- ignoreBody: false,
87
- ignoreQuerystring: false,
88
- parameter: [],
89
- querystringPolicy: null,
90
- }
91
- });
92
- });
93
-
94
- it('updates policy from app settings and server features', function () {
95
- let policy = core.protect.getPolicy();
96
-
97
- expect(policy).to.deep.include({
98
- rulesMask: 20,
99
- 'bot-blocker': 'off',
100
- 'cmd-injection': 'block',
101
- 'cmd-injection-command-backdoors': 'off',
102
- 'cmd-injection-semantic-chained-commands': 'off',
103
- 'cmd-injection-semantic-dangerous-paths': 'off',
104
- 'ip-denylist': 'off',
105
- 'method-tampering': 'off',
106
- 'nosql-injection': 'off',
107
- 'nosql-injection-mongo': 'off',
108
- 'path-traversal': 'off',
109
- 'path-traversal-semantic-file-security-bypass': 'off',
110
- 'reflected-xss': 'block_at_perimeter',
111
- 'sql-injection': 'off',
112
- 'ssjs-injection': 'off',
113
- 'ssrf': 'off',
114
- 'unsafe-code-execution': 'off',
115
- 'unsafe-file-upload': 'off',
116
- 'untrusted-deserialization': 'off',
117
- 'unvalidated-redirect': 'off',
118
- 'virtual-patch': 'off',
119
- 'xxe': 'off',
120
- exclusions: {
121
- bodyPolicy: null,
122
- cookie: [],
123
- header: [],
124
- ignoreBody: false,
125
- ignoreQuerystring: false,
126
- parameter: [],
127
- querystringPolicy: null,
128
- }
129
- });
130
-
131
- core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
132
- protect: {
133
- rules: {
134
- 'cmd-injection': { mode: 'MONITOR' },
135
- 'method-tampering': { mode: 'BLOCK_AT_PERIMETER' },
136
- 'nosql-injection': { mode: 'MONITOR' },
137
- 'ssjs-injection': { mode: 'BLOCK' },
138
- }
139
- }
140
- });
141
-
142
- policy = core.protect.getPolicy();
143
-
144
- expect(policy).to.deep.include({
145
- rulesMask: 436,
146
- 'bot-blocker': 'off',
147
- 'cmd-injection': 'block',
148
- 'cmd-injection-command-backdoors': 'off',
149
- 'cmd-injection-semantic-chained-commands': 'off',
150
- 'cmd-injection-semantic-dangerous-paths': 'off',
151
- 'ip-denylist': 'off',
152
- 'method-tampering': 'block_at_perimeter',
153
- 'nosql-injection': 'monitor',
154
- 'nosql-injection-mongo': 'monitor',
155
- 'path-traversal': 'off',
156
- 'path-traversal-semantic-file-security-bypass': 'off',
157
- 'reflected-xss': 'block_at_perimeter',
158
- 'sql-injection': 'off',
159
- 'ssjs-injection': 'block',
160
- 'ssrf': 'off',
161
- 'unsafe-code-execution': 'off',
162
- 'unsafe-file-upload': 'off',
163
- 'untrusted-deserialization': 'off',
164
- 'unvalidated-redirect': 'off',
165
- 'virtual-patch': 'off',
166
- 'xxe': 'off',
167
- exclusions: {
168
- bodyPolicy: null,
169
- cookie: [],
170
- header: [],
171
- ignoreBody: false,
172
- ignoreQuerystring: false,
173
- parameter: [],
174
- querystringPolicy: null,
175
- }
176
- });
177
-
178
- core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
179
- protect: {
180
- rules: {
181
- bot_blocker: {
182
- enable: true
183
- }
184
- }
185
- }
186
- });
187
-
188
- policy = core.protect.getPolicy();
189
-
190
- expect(policy).to.deep.include({
191
- rulesMask: 500,
192
- 'bot-blocker': 'block_at_perimeter',
193
- 'cmd-injection': 'block',
194
- 'cmd-injection-command-backdoors': 'off',
195
- 'cmd-injection-semantic-chained-commands': 'off',
196
- 'cmd-injection-semantic-dangerous-paths': 'off',
197
- 'ip-denylist': 'off',
198
- 'method-tampering': 'block_at_perimeter',
199
- 'nosql-injection': 'monitor',
200
- 'nosql-injection-mongo': 'monitor',
201
- 'path-traversal': 'off',
202
- 'path-traversal-semantic-file-security-bypass': 'off',
203
- 'reflected-xss': 'block_at_perimeter',
204
- 'sql-injection': 'off',
205
- 'ssjs-injection': 'block',
206
- 'ssrf': 'off',
207
- 'unsafe-code-execution': 'off',
208
- 'unsafe-file-upload': 'off',
209
- 'untrusted-deserialization': 'off',
210
- 'unvalidated-redirect': 'off',
211
- 'virtual-patch': 'off',
212
- 'xxe': 'off',
213
- exclusions: {
214
- bodyPolicy: null,
215
- cookie: [],
216
- header: [],
217
- ignoreBody: false,
218
- ignoreQuerystring: false,
219
- parameter: [],
220
- querystringPolicy: null,
221
- }
222
- });
223
- });
224
-
225
- describe('special case: nosql-injection-mongo', function() {
226
- it('nosql-injection-mongo will not get updated by nosql-injection settings if set in config', function () {
227
- core.config.setValue(`protect.rules.${Rule.NOSQL_INJECTION_MONGO}.mode`, 'block', ConfigSource.USER_CONFIGURATION_FILE);
228
- const getPolicy = policyFactory(core);
229
- let policy = getPolicy();
230
-
231
- expect(policy).to.deep.include({
232
- 'nosql-injection': 'off',
233
- 'nosql-injection-mongo': 'block',
234
- });
235
-
236
- core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
237
- protect: {
238
- rules: {
239
- 'nosql-injection': { mode: 'MONITOR' },
240
- }
241
- }
242
- });
243
-
244
- policy = core.protect.getPolicy();
245
- expect(policy).to.deep.include({
246
- 'nosql-injection': 'monitor',
247
- 'nosql-injection-mongo': 'block',
248
- });
249
- });
250
-
251
- it('nosql-injection-mongo will inherit nosql-injection config if unset itself', function () {
252
- core.config.setValue(`protect.rules.${Rule.NOSQL_INJECTION}.mode`, 'block', ConfigSource.USER_CONFIGURATION_FILE);
253
- const getPolicy = policyFactory(core);
254
- const policy = getPolicy();
255
-
256
- expect(policy).to.deep.include({
257
- 'nosql-injection': 'block',
258
- 'nosql-injection-mongo': 'block',
259
- });
260
- });
261
- });
262
- });
263
-
264
- describe('policy building accounts for UI-defined exclusions', function () {
265
- beforeEach(function () {
266
- core.config.protect.rules['path-traversal'].mode = 'monitor';
267
- core.config.protect.rules['sql-injection'].mode = 'monitor';
268
- core.config.protect.rules['cmd-injection'].mode = 'monitor';
269
- core.config.protect.rules['reflected-xss'].mode = 'monitor';
270
- core.config.protect.rules.disabled_rules = [];
271
- policyFactory(core);
272
- core.messages.emit(Event.SERVER_SETTINGS_UPDATE, exclusionSettingsMessage);
273
- });
274
-
275
- const baseline = {
276
- rulesMask: 30,
277
- 'bot-blocker': 'off',
278
- 'cmd-injection': 'monitor',
279
- 'cmd-injection-command-backdoors': 'off',
280
- 'cmd-injection-semantic-chained-commands': 'off',
281
- 'cmd-injection-semantic-dangerous-paths': 'off',
282
- 'ip-denylist': 'off',
283
- 'method-tampering': 'off',
284
- 'nosql-injection': 'off',
285
- 'nosql-injection-mongo': 'off',
286
- 'path-traversal': 'monitor',
287
- 'path-traversal-semantic-file-security-bypass': 'off',
288
- 'reflected-xss': 'monitor',
289
- 'sql-injection': 'monitor',
290
- 'ssjs-injection': 'off',
291
- 'unsafe-code-execution': 'off',
292
- 'unsafe-file-upload': 'off',
293
- 'untrusted-deserialization': 'off',
294
- 'virtual-patch': 'off',
295
- 'xxe': 'off',
296
- exclusions: {
297
- ignoreQuerystring: false,
298
- querystringPolicy: null,
299
- ignoreBody: false,
300
- bodyPolicy: null,
301
- cookie: [],
302
- header: [],
303
- parameter: [{
304
- policy: { 'sql-injection': 'off' }
305
- }],
306
- }
307
- };
308
-
309
- [
310
- { uriPath: 'baseline', expectedPolicy: baseline },
311
- { uriPath: '/url-exclusion-all-rules', expectedPolicy: null },
312
- {
313
- uriPath: '/url-exclusion-some-rules',
314
- expectedPolicy: {
315
- ...baseline,
316
- rulesMask: 28,
317
- 'path-traversal': 'off',
318
- }
319
- },
320
- {
321
- uriPath: '/input-exclusion-some-rules',
322
- expectedPolicy: {
323
- ...baseline,
324
- exclusions: {
325
- parameter: [{
326
- policy: {
327
- 'sql-injection': 'off',
328
- }
329
- }]
330
- }
331
- }
332
- },
333
- {
334
- uriPath: '/input-exclusion-more-rules',
335
- expectedPolicy: {
336
- ...baseline,
337
- exclusions: {
338
- header: [{
339
- policy: {
340
- 'cmd-injection': 'off',
341
- 'sql-injection': 'off',
342
- 'path-traversal': 'off',
343
- 'reflected-xss': 'off',
344
- }
345
- }],
346
- parameter: [{
347
- policy: { 'sql-injection': 'off' }
348
- }, {
349
- policy: {
350
- 'cmd-injection': 'off',
351
- 'sql-injection': 'off',
352
- 'path-traversal': 'off',
353
- }
354
- }]
355
- }
356
- }
357
- },
358
- {
359
- uriPath: '/input-exclusion-body-some-rules',
360
- expectedPolicy: {
361
- ...baseline,
362
- exclusions: {
363
- bodyPolicy: {
364
- 'cmd-injection': 'off',
365
- 'sql-injection': 'off',
366
- 'path-traversal': 'off',
367
- 'reflected-xss': 'off',
368
- }
369
- }
370
- }
371
- },
372
- {
373
- uriPath: '/input-exclusion-body-all-rules',
374
- expectedPolicy: {
375
- ...baseline,
376
- exclusions: {
377
- ignoreBody: true
378
- }
379
- }
380
- },
381
- {
382
- uriPath: '/input-exclusion-querystring-some-rules',
383
- expectedPolicy: {
384
- ...baseline,
385
- exclusions: {
386
- querystringPolicy: {
387
- 'nosql-injection-mongo': 'off',
388
- 'sql-injection': 'off',
389
- 'path-traversal': 'off',
390
- 'reflected-xss': 'off',
391
- }
392
- }
393
- }
394
- },
395
- {
396
- uriPath: '/input-exclusion-querystring-all-rules',
397
- expectedPolicy: {
398
- ...baseline,
399
- exclusions: {
400
- ignoreQuerystring: true
401
- }
402
- },
403
- },
404
- {
405
- uriPath: '/input-exclusion-cookie-all-rules',
406
- expectedPolicy: {
407
- ...baseline,
408
- exclusions: {
409
- cookie: [{
410
- name: '.*',
411
- }],
412
- }
413
- }
414
- }
415
- ].forEach(({ uriPath, expectedPolicy }) => {
416
- it(`builds exclusions correctly for uriPath=${uriPath}`, function () {
417
- expect(core.protect.getPolicy({ uriPath })).to.be.like(expectedPolicy);
418
-
419
- });
420
- });
421
- });
422
-
423
- describe('handles errors during exclusion compilation', function () {
424
- it('catches the error and logs a message for it', function () {
425
- const exclusionDtm = {
426
- urls: [
427
- '.*******'
428
- ],
429
- matchStrategy: 'ONLY',
430
- protect_rules: [],
431
- modes: [
432
- 'defend'
433
- ],
434
- name: 'UrlExclusionAllRules'
435
- };
436
-
437
- core.messages.emit(Event.SERVER_SETTINGS_UPDATE, {
438
- exclusions: {
439
- input: [],
440
- url: [exclusionDtm]
441
- }
442
- });
443
- expect(core.logger.error).to.have.been.calledOnceWithExactly({ err: sinon.match.any, exclusionDtm }, 'failed to process exclusion');
444
- });
445
- });
446
- });