@contrast/protect 1.18.0 → 1.20.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.
@@ -692,7 +692,7 @@ module.exports = function(core) {
692
692
  key: type === 'Key' ? value : path[path.length - 1],
693
693
  value,
694
694
  score: item.score,
695
- idsList: [],
695
+ idsList: item.idsList || [],
696
696
  };
697
697
  if (item.mongoContext) {
698
698
  result.mongoContext = item.mongoContext;
@@ -22,6 +22,7 @@ const {
22
22
  isString,
23
23
  traverseKeys,
24
24
  traverseKeysAndValues,
25
+ agentLibIDListTypes
25
26
  } = require('@contrast/common');
26
27
 
27
28
  module.exports = function(core) {
@@ -127,10 +128,30 @@ module.exports = function(core) {
127
128
  }
128
129
  };
129
130
 
130
- inputTracing.nosqlInjectionMongo = function(sourceContext, sinkContext) {
131
+ inputTracing.nosqlInjectionMongo = function (sourceContext, sinkContext) {
131
132
  const ruleId = 'nosql-injection-mongo';
132
- const expansionResults = getResultsByRuleId(ruleId, sourceContext);
133
- const stringInjectionResults = getResultsByRuleId('ssjs-injection', sourceContext);
133
+ const nosqlInjectionMongoResults =
134
+ getResultsByRuleId(ruleId, sourceContext) || [];
135
+ const ssjsInjectionResults =
136
+ getResultsByRuleId('ssjs-injection', sourceContext) || [];
137
+
138
+ const stringInjectionResults = [...ssjsInjectionResults];
139
+ const expansionResults = [];
140
+
141
+ nosqlInjectionMongoResults.forEach((result) => {
142
+ if (
143
+ result.idsList &&
144
+ result.idsList.some(
145
+ (el) =>
146
+ el === agentLibIDListTypes.MONGO_SLEEP ||
147
+ el === agentLibIDListTypes.TRUE_CLAUSE_1
148
+ )
149
+ ) {
150
+ stringInjectionResults.push(result);
151
+ } else {
152
+ expansionResults.push(result);
153
+ }
154
+ });
134
155
 
135
156
  if (expansionResults) {
136
157
  let expansionFindings = null;
@@ -138,7 +159,13 @@ module.exports = function(core) {
138
159
  expansionFindings = handleObjectValue(result, sinkContext.value);
139
160
 
140
161
  if (expansionFindings) {
141
- handleFindings(sourceContext, sinkContext, ruleId, result, expansionFindings);
162
+ handleFindings(
163
+ sourceContext,
164
+ sinkContext,
165
+ ruleId,
166
+ result,
167
+ expansionFindings
168
+ );
142
169
  }
143
170
  }
144
171
  }
@@ -148,30 +175,44 @@ module.exports = function(core) {
148
175
 
149
176
  for (const result of stringInjectionResults) {
150
177
  if (typeof sinkContext.value === 'object') {
151
- traverseKeysAndValues(sinkContext.value, function(path, type, value, obj) {
152
- if (type !== 'Key' && !agentLib.isMongoQueryType(value)) return;
153
-
154
- if (!stringFindings && type == 'Key' && value == '$accumulator') {
155
- stringFindings =
156
- handleStringValue(result, obj[value]?.['init'], agentLib) ||
157
- handleStringValue(result, obj[value]?.['merge'], agentLib) ||
158
- handleStringValue(result, obj[value]?.['finalize'], agentLib) ||
159
- handleStringValue(result, obj[value]?.['accumulate'], agentLib);
160
- }
161
-
162
- if (!stringFindings && type == 'Key' && value == '$function') {
163
- stringFindings =
164
- handleStringValue(result, obj['$function']?.body, agentLib);
165
- }
166
-
167
- if (!stringFindings) {
168
- stringFindings = handleStringValue(result, obj[value], agentLib);
178
+ traverseKeysAndValues(
179
+ sinkContext.value,
180
+ function (path, type, value, obj) {
181
+ if (type !== 'Key' && !agentLib.isMongoQueryType(value)) return;
182
+
183
+ if (!stringFindings && type == 'Key' && value == '$accumulator') {
184
+ stringFindings =
185
+ handleStringValue(result, obj[value]?.init, agentLib) ||
186
+ handleStringValue(result, obj[value]?.merge, agentLib) ||
187
+ handleStringValue(result, obj[value]?.finalize, agentLib) ||
188
+ handleStringValue(result, obj[value]?.accumulate, agentLib);
189
+ }
190
+
191
+ if (!stringFindings && type == 'Key' && value == '$function') {
192
+ stringFindings = handleStringValue(
193
+ result,
194
+ obj['$function']?.body,
195
+ agentLib
196
+ );
197
+ }
198
+
199
+ if (!stringFindings) {
200
+ stringFindings = handleStringValue(
201
+ result,
202
+ obj[value],
203
+ agentLib
204
+ );
205
+ }
206
+
207
+ if (stringFindings) return true;
169
208
  }
170
-
171
- if (stringFindings) return true;
172
- });
209
+ );
173
210
  } else if (typeof sinkContext.value === 'string') {
174
- stringFindings = handleStringValue(result, sinkContext.value, agentLib);
211
+ stringFindings = handleStringValue(
212
+ result,
213
+ sinkContext.value,
214
+ agentLib
215
+ );
175
216
  }
176
217
 
177
218
  if (stringFindings) {
@@ -184,7 +225,13 @@ module.exports = function(core) {
184
225
  sourceContext.resultsMap[ruleId] = [nosqlInjectionResult];
185
226
  }
186
227
 
187
- handleFindings(sourceContext, sinkContext, ruleId, nosqlInjectionResult, stringFindings);
228
+ handleFindings(
229
+ sourceContext,
230
+ sinkContext,
231
+ ruleId,
232
+ nosqlInjectionResult,
233
+ stringFindings
234
+ );
188
235
  }
189
236
  }
190
237
  }
@@ -26,7 +26,7 @@ module.exports = function (core) {
26
26
 
27
27
  function getCursorQueryData(args, version) {
28
28
  const query = semver.gte(version, '3.3.0')
29
- ? args[0]?.cmd?.query
29
+ ? args[0]?.cmd?.query || args[1]?.query
30
30
  : args[1]?.query;
31
31
 
32
32
  if (!query) {
@@ -67,12 +67,12 @@ module.exports = function (core) {
67
67
  inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
68
68
  }
69
69
 
70
- function v4CollectionVal({ args, ...ctx }) {
70
+ function CollectionVal({ args, ...ctx }) {
71
71
  const value = typeof args[0] == 'function' ? null : args[0];
72
72
  preHook(value, ctx);
73
73
  }
74
74
 
75
- function v4DbVal({ args, ...ctx }) {
75
+ function dbCommandVal({ args, ...ctx }) {
76
76
  const value = args[0]?.filter;
77
77
  preHook(value, ctx);
78
78
  }
@@ -87,7 +87,7 @@ module.exports = function (core) {
87
87
  preHook(value, ctx);
88
88
  }
89
89
 
90
- function v3DbVal({ args, ...ctx }) {
90
+ function firstArgVal({ args, ...ctx }) {
91
91
  const value = args[0];
92
92
  preHook(value, ctx);
93
93
  }
@@ -106,16 +106,19 @@ module.exports = function (core) {
106
106
  [
107
107
  {
108
108
  moduleName,
109
- version: '>=4.0.0',
109
+ version: '>=2.0.0 <3.0.0 || >=4.0.0',
110
110
  patchObjects: [
111
111
  {
112
112
  name: 'Collection.prototype',
113
113
  methods: [
114
+ 'update',
114
115
  'updateOne',
115
116
  'replaceOne',
116
117
  'updateMany',
118
+ 'remove',
117
119
  'deleteOne',
118
120
  'deleteMany',
121
+ 'findAndModify',
119
122
  'findOneAndDelete',
120
123
  'findOneAndReplace',
121
124
  'findOneAndUpdate',
@@ -125,13 +128,13 @@ module.exports = function (core) {
125
128
  'aggregate'
126
129
  ],
127
130
  patchType,
128
- preHookFn: v4CollectionVal
131
+ preHookFn: CollectionVal
129
132
  },
130
133
  {
131
134
  name: 'Db.prototype',
132
135
  methods: ['command'],
133
136
  patchType,
134
- preHookFn: v4DbVal
137
+ preHookFn: dbCommandVal
135
138
  }
136
139
  ]
137
140
  },
@@ -157,18 +160,30 @@ module.exports = function (core) {
157
160
  patchType,
158
161
  preHookFn: v3CursorVal
159
162
  },
163
+ {
164
+ name: 'Db.prototype',
165
+ methods: ['command'],
166
+ patchType,
167
+ preHookFn: dbCommandVal
168
+ },
160
169
  {
161
170
  name: 'Db.prototype',
162
171
  methods: ['eval'],
163
172
  patchType,
164
- preHookFn: v3DbVal
165
- }
173
+ preHookFn: firstArgVal
174
+ },
175
+ {
176
+ name: 'Collection.prototype',
177
+ methods: ['find'],
178
+ patchType,
179
+ preHookFn: firstArgVal
180
+ },
166
181
  ]
167
182
  },
168
183
  {
169
184
  moduleName,
170
185
  file: 'lib/topologies/topology_base.js',
171
- version: '<4.0.0',
186
+ version: '<4.0.0 >=3.0.0',
172
187
  patchObjects: [
173
188
  {
174
189
  name: 'TopologyBase.prototype',
@@ -187,7 +202,7 @@ module.exports = function (core) {
187
202
  {
188
203
  moduleName,
189
204
  file: 'lib/topologies/native_topology.js',
190
- version: '<4.0.0',
205
+ version: '<4.0.0 >=3.0.0',
191
206
  patchObjects: [
192
207
  {
193
208
  name: 'NativeTopology.prototype',
@@ -204,7 +219,7 @@ module.exports = function (core) {
204
219
  preHookFn: v3CursorVal
205
220
  }
206
221
  ]
207
- }
222
+ },
208
223
  ].forEach(({ moduleName, file, version, patchObjects }) => {
209
224
  instrument({
210
225
  moduleName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/protect",
3
- "version": "1.18.0",
3
+ "version": "1.20.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)",
@@ -17,11 +17,11 @@
17
17
  "test": "../scripts/test.sh"
18
18
  },
19
19
  "dependencies": {
20
- "@contrast/agent-lib": "^5.3.4",
21
- "@contrast/common": "1.9.0",
22
- "@contrast/core": "1.16.0",
23
- "@contrast/esm-hooks": "1.12.0",
24
- "@contrast/scopes": "1.3.0",
20
+ "@contrast/agent-lib": "^7.0.1",
21
+ "@contrast/common": "1.11.0",
22
+ "@contrast/core": "1.18.0",
23
+ "@contrast/esm-hooks": "1.14.0",
24
+ "@contrast/scopes": "1.4.0",
25
25
  "ipaddr.js": "^2.0.1",
26
26
  "semver": "^7.3.7"
27
27
  },