@contrast/protect 1.15.1 → 1.16.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.
@@ -115,44 +115,15 @@ module.exports = function(core) {
115
115
  }
116
116
 
117
117
  function install() {
118
- [{
119
- moduleName: 'http'
120
- },
121
- {
122
- moduleName: 'https'
123
- },
124
- {
125
- moduleName: 'spdy'
126
- },
127
- {
128
- moduleName: 'http2',
129
- patchObjectsProps: [
130
- {
131
- methods: ['createServer', 'createSecureServer'],
132
- patchType,
133
- patchObjects: [
134
- {
135
- name: 'Server.prototype',
136
- methods: ['emit'],
137
- patchType,
138
- around
139
- }
140
- ]
141
- }
142
- ]
143
- }].forEach(({ moduleName, patchObjectsProps }) => {
144
- const patchObjects = patchObjectsProps || [
145
- {
118
+ ['http', 'https', 'spdy', 'http2'].forEach((moduleName) => {
119
+ instrument({
120
+ moduleName,
121
+ patchObjects: [{
146
122
  name: 'Server.prototype',
147
123
  methods: ['emit'],
148
124
  patchType,
149
125
  around
150
- }
151
- ];
152
-
153
- instrument({
154
- moduleName,
155
- patchObjects
126
+ }]
156
127
  });
157
128
  });
158
129
  }
@@ -29,8 +29,8 @@ module.exports = (core) => {
29
29
 
30
30
  messages.on(Event.SERVER_SETTINGS_UPDATE, (serverUpdate) => {
31
31
  const now = new Date().getTime();
32
- const updatedIpAllowList = serverUpdate.features?.defend?.ipAllowlist?.map?.((ipEntry) => ipEntryMap(ipEntry, now));
33
- const updatedIpDenyList = serverUpdate.features?.defend?.ipDenylist?.map?.((ipEntry) => ipEntryMap(ipEntry, now));
32
+ const updatedIpAllowList = serverUpdate.protect?.rules?.ip_allowlist?.map?.((ipEntry) => ipEntryMap(ipEntry, now));
33
+ const updatedIpDenyList = serverUpdate.protect?.rules?.ip_denylist?.map?.((ipEntry) => ipEntryMap(ipEntry, now));
34
34
 
35
35
  if (updatedIpAllowList) {
36
36
  ipAllowlist.length = 0;
@@ -26,7 +26,7 @@ module.exports = (core) => {
26
26
  const virtualPatchesEvaluators = inputAnalysis.virtualPatchesEvaluators = [];
27
27
 
28
28
  messages.on(Event.SERVER_SETTINGS_UPDATE, (serverUpdate) => {
29
- const virtualPatches = serverUpdate.settings?.defend?.virtualPatches;
29
+ const virtualPatches = serverUpdate.protect?.['virtual-patches'];
30
30
  if (virtualPatches) {
31
31
  buildVPEvaluators(virtualPatches, virtualPatchesEvaluators);
32
32
  }
package/lib/policy.js CHANGED
@@ -112,8 +112,9 @@ module.exports = function(core) {
112
112
  function readModeFromSetting(remoteSetting) {
113
113
  switch (remoteSetting.mode) {
114
114
  case 'OFF': return OFF;
115
- case 'MONITORING': return MONITOR;
116
- case 'BLOCKING': return remoteSetting.blockAtEntry ? BLOCK_AT_PERIMETER : BLOCK;
115
+ case 'MONITOR': return MONITOR;
116
+ case 'BLOCK': return BLOCK;
117
+ case 'BLOCK_AT_PERIMETER': return BLOCK_AT_PERIMETER;
117
118
  }
118
119
  }
119
120
 
@@ -133,17 +134,16 @@ module.exports = function(core) {
133
134
  * @param {[]} protectionRules
134
135
  */
135
136
  function updateFromProtectionRules(protectionRules) {
136
- for (const remoteSetting of Object.values(protectionRules)) {
137
- const { id: ruleId } = remoteSetting;
137
+ for (const ruleId in protectionRules) {
138
138
  if (ruleId === 'nosql-injection' && !getModeFromConfig('nosql-injection-mongo')) {
139
- policy['nosql-injection-mongo'] = readModeFromSetting(remoteSetting);
139
+ policy['nosql-injection-mongo'] = readModeFromSetting(protectionRules[ruleId]);
140
140
  }
141
141
 
142
142
  if (getModeFromConfig(ruleId)) {
143
143
  continue;
144
144
  }
145
145
 
146
- policy[ruleId] = readModeFromSetting(remoteSetting);
146
+ policy[ruleId] && (policy[ruleId] = readModeFromSetting(protectionRules[ruleId]));
147
147
 
148
148
  }
149
149
  }
@@ -253,14 +253,12 @@ module.exports = function(core) {
253
253
  function updateGlobalPolicy(remoteSettings) {
254
254
  let update;
255
255
 
256
- const protectionRules = remoteSettings?.settings?.defend?.protectionRules;
256
+ const protectionRules = remoteSettings?.protect?.rules;
257
257
  if (protectionRules) {
258
258
  updateFromProtectionRules(protectionRules);
259
259
  update = 'application-settings';
260
- }
261
260
 
262
- if (remoteSettings?.features?.defend) {
263
- const bbEnabled = remoteSettings.features.defend[BOT_BLOCKER];
261
+ const bbEnabled = remoteSettings.protect.rules?.bot_blocker?.enable;
264
262
 
265
263
  if (
266
264
  bbEnabled != null &&
@@ -268,30 +266,30 @@ module.exports = function(core) {
268
266
  !config.protect.rules?.[BOT_BLOCKER]?.mode
269
267
  ) {
270
268
  policy[BOT_BLOCKER] = bbEnabled ? BLOCK_AT_PERIMETER : OFF;
271
- update = 'server-features';
272
269
  }
273
270
  }
274
271
 
275
272
  if (update) {
276
273
  updateRulesMask();
274
+ protect.policy.exclusions = compiled;
277
275
  logger.info({ policy: protect.policy }, `protect policy updated from ${update}`);
278
276
  }
279
277
  }
280
278
 
281
279
  function updateExclusions(serverUpdate) {
282
280
  const exclusions = [
283
- ...(serverUpdate.settings?.exceptions?.inputExceptions || []),
284
- ...(serverUpdate.settings?.exceptions?.urlExceptions || [])
281
+ ...(serverUpdate?.exclusions?.input || []),
282
+ ...(serverUpdate?.exclusions?.url || [])
285
283
  ].filter((exclusion) => exclusion.modes.includes('defend'));
286
284
 
287
285
  if (!exclusions.length) return;
288
286
  compiled = initCompiled();
289
287
 
290
288
  for (const exclusionDtm of exclusions) {
291
- exclusionDtm.inputType = exclusionDtm.inputType || 'URL';
289
+ exclusionDtm.type = exclusionDtm.type || 'URL';
292
290
 
293
- const { name, rules, inputName, urls, inputType } = exclusionDtm;
294
- const key = inputType.toLowerCase();
291
+ const { name, protect_rules, urls, type } = exclusionDtm;
292
+ const key = type.toLowerCase();
295
293
 
296
294
  if (!compiled[key]) continue;
297
295
 
@@ -299,15 +297,15 @@ module.exports = function(core) {
299
297
  const e = { name };
300
298
  e.matchesUriPath = createUriPathMatcher(urls);
301
299
 
302
- if (inputName) {
303
- e.matchesInputName = createInputNameMatcher(inputName);
300
+ if (name) {
301
+ e.matchesInputName = createInputNameMatcher(name);
304
302
  }
305
303
 
306
- if (rules.length) {
304
+ if (protect_rules.length) {
307
305
  let rulesMask = 0;
308
306
  const exclusionPolicy = {};
309
307
 
310
- for (let ruleId of rules) {
308
+ for (let ruleId of protect_rules) {
311
309
  // todo: this doesn't seem to make a difference?
312
310
  if (ruleId === 'nosql-injection') {
313
311
  ruleId = 'nosql-injection-mongo';
@@ -315,7 +313,7 @@ module.exports = function(core) {
315
313
 
316
314
  if (agentLib.RuleType[ruleId]) {
317
315
  Object.assign(exclusionPolicy, { [ruleId]: OFF });
318
- if (inputType === 'URL') {
316
+ if (type === 'URL') {
319
317
  rulesMask = rulesMask | agentLib.RuleType[ruleId];
320
318
  exclusionPolicy.rulesMask = rulesMask;
321
319
  }
@@ -345,8 +343,8 @@ module.exports = function(core) {
345
343
  }
346
344
 
347
345
  messages.on(SERVER_SETTINGS_UPDATE, (msg) => {
348
- updateGlobalPolicy(msg);
349
346
  updateExclusions(msg);
347
+ updateGlobalPolicy(msg);
350
348
  });
351
349
 
352
350
  initPolicy();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/protect",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
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)",
@@ -18,9 +18,9 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@contrast/agent-lib": "^5.3.4",
21
- "@contrast/common": "1.6.0",
22
- "@contrast/core": "1.13.1",
23
- "@contrast/esm-hooks": "1.9.1",
21
+ "@contrast/common": "1.7.0",
22
+ "@contrast/core": "1.14.0",
23
+ "@contrast/esm-hooks": "1.10.0",
24
24
  "@contrast/scopes": "1.3.0",
25
25
  "ipaddr.js": "^2.0.1",
26
26
  "semver": "^7.3.7"