@contrast/agent 4.9.1 → 4.10.3

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 (38) hide show
  1. package/bin/VERSION +1 -1
  2. package/bin/linux/contrast-service +0 -0
  3. package/bin/mac/contrast-service +0 -0
  4. package/bin/windows/contrast-service.exe +0 -0
  5. package/bootstrap.js +2 -2
  6. package/lib/assess/propagators/joi/any.js +48 -0
  7. package/lib/assess/propagators/joi/index.js +2 -0
  8. package/lib/assess/propagators/joi/object.js +61 -0
  9. package/lib/assess/propagators/joi/string-base.js +16 -0
  10. package/lib/assess/propagators/mongoose/helpers.js +36 -1
  11. package/lib/assess/propagators/mongoose/index.js +1 -0
  12. package/lib/assess/propagators/mongoose/map.js +19 -31
  13. package/lib/assess/propagators/mongoose/mixed.js +71 -0
  14. package/lib/assess/propagators/mongoose/string.js +8 -0
  15. package/lib/core/arch-components/mysql.js +25 -15
  16. package/lib/core/arch-components/postgres.js +36 -26
  17. package/lib/core/arch-components/util.js +49 -0
  18. package/lib/core/config/options.js +11 -9
  19. package/lib/core/express/index.js +8 -3
  20. package/lib/core/fastify/index.js +2 -1
  21. package/lib/core/hapi/index.js +2 -1
  22. package/lib/core/koa/index.js +9 -1
  23. package/lib/core/logger/debug-logger.js +4 -3
  24. package/lib/core/rewrite/binary-expression.js +1 -2
  25. package/lib/core/rewrite/callees.js +19 -2
  26. package/lib/core/rewrite/catch-clause.js +4 -2
  27. package/lib/core/rewrite/import-declaration.js +71 -0
  28. package/lib/core/rewrite/index.js +10 -7
  29. package/lib/core/rewrite/injections.js +6 -4
  30. package/lib/core/rewrite/rewrite-log.js +5 -8
  31. package/lib/protect/restify/sources.js +35 -0
  32. package/lib/protect/rules/nosqli/nosql-injection-rule.js +30 -16
  33. package/lib/protect/rules/nosqli/nosql-scanner/index.js +1 -1
  34. package/lib/protect/rules/nosqli/nosql-scanner/rethinkdbscanner.js +26 -0
  35. package/lib/protect/sinks/index.js +2 -0
  36. package/lib/protect/sinks/mongodb.js +1 -3
  37. package/lib/protect/sinks/rethinkdb.js +47 -0
  38. package/package.json +23 -15
@@ -173,7 +173,8 @@ class HapiCore {
173
173
  decorateRequest({
174
174
  normalizedUri: get(request, 'route.path'),
175
175
  body: request.payload,
176
- parameters: request.params
176
+ parameters: request.params,
177
+ query: request.query
177
178
  });
178
179
  return h.continue;
179
180
  });
@@ -216,13 +216,21 @@ class KoaCore {
216
216
  */
217
217
  registerRequestHandler(ctx) {
218
218
  ctx.req.request = ctx.request;
219
+ const { query } = ctx.request;
219
220
  ctx.request = new Proxy(ctx.request, {
220
221
  set(...args) {
221
222
  const [obj, prop] = args;
222
223
  const result = Reflect.set(...args);
224
+ if (query) {
225
+ decorateRequest({
226
+ query
227
+ });
228
+ }
223
229
  switch (prop) {
224
230
  case 'body':
225
- decorateRequest({ body: obj[prop] });
231
+ decorateRequest({
232
+ body: obj[prop]
233
+ });
226
234
  agentEmitter.emit(constants.EVENTS.CTX_REQUEST_BODY, {
227
235
  request: obj,
228
236
  ctx
@@ -108,9 +108,10 @@ class DebugLogFactory {
108
108
 
109
109
  // We always log to a file, but check whether we should log to stdout
110
110
  if (
111
- !this.stdout ||
112
- !process.env.DEBUG ||
113
- !/(^|,\s*)contrast:.+/.test(process.env.DEBUG)
111
+ this.loggerPath &&
112
+ (!this.stdout ||
113
+ !process.env.DEBUG ||
114
+ !/(^|,\s*)contrast:.+/.test(process.env.DEBUG))
114
115
  ) {
115
116
  this.mute = true;
116
117
  }
@@ -15,7 +15,6 @@ Copyright: 2022 Contrast Security, Inc
15
15
  'use strict';
16
16
 
17
17
  const t = require('@babel/types');
18
- const _ = require('lodash');
19
18
 
20
19
  /**
21
20
  * Wraps binary expressions in one of the following: `ContrastMethods.__add`,
@@ -30,7 +29,7 @@ const _ = require('lodash');
30
29
  * @param {import('.').State} state
31
30
  */
32
31
  module.exports = function BinaryExpression(path, state) {
33
- const spec = _.find(state.specs, { token: path.node.operator });
32
+ const spec = state.specs.find(({ token }) => token === path.node.operator);
34
33
  if (
35
34
  !spec ||
36
35
  !state.callees[spec.name] ||
@@ -15,7 +15,6 @@ Copyright: 2022 Contrast Security, Inc
15
15
  'use strict';
16
16
 
17
17
  const { expression } = require('@babel/template');
18
- const _ = require('lodash');
19
18
 
20
19
  /**
21
20
  * @typedef {Object} Spec
@@ -67,6 +66,22 @@ const specs = [
67
66
  token: 'eval',
68
67
  modes: { assess: true, protect: true }
69
68
  },
69
+ // Import Declaration
70
+ {
71
+ name: '__importDefault',
72
+ type: 'ImportDefaultSpecifier',
73
+ modes: { assess: true, protect: true }
74
+ },
75
+ {
76
+ name: '__importNamespace',
77
+ type: 'ImportNamespaceSpecifier',
78
+ modes: { assess: true, protect: true }
79
+ },
80
+ {
81
+ name: '__import',
82
+ type: 'ImportSpecifier',
83
+ modes: { assess: true, protect: true }
84
+ },
70
85
  // Member Expression
71
86
  {
72
87
  name: '__forceCopy',
@@ -116,7 +131,9 @@ module.exports = function createCallees(agent) {
116
131
  const callees = specs.reduce(
117
132
  (memo, spec) =>
118
133
  (assessMode && spec.modes.assess) || (protectMode && spec.modes.protect)
119
- ? _.set(memo, spec.name, calleeBuilder({ name: spec.name }))
134
+ ? Object.assign(memo, {
135
+ [spec.name]: calleeBuilder({ name: spec.name })
136
+ })
120
137
  : memo,
121
138
  {}
122
139
  );
@@ -13,7 +13,6 @@ Copyright: 2022 Contrast Security, Inc
13
13
  way not consistent with the End User License Agreement.
14
14
  */
15
15
  const { statement } = require('@babel/template');
16
- const _ = require('lodash');
17
16
 
18
17
  const logStatementBuilder = statement(
19
18
  `if (global.CONTRAST_LOG) {
@@ -38,7 +37,10 @@ const logStatementBuilder = statement(
38
37
  * @param {import('.').State} state
39
38
  */
40
39
  module.exports = function CatchClause(path, state) {
41
- if (!_.get(state.agent, 'config.agent.node.enable_catch_log')) return;
40
+ const { config } = state.agent;
41
+ if (!config || !config.agent.node.enable_catch_log) {
42
+ return;
43
+ }
42
44
 
43
45
  path.node.param = path.node.param || path.scope.generateUidIdentifier('err');
44
46
  path
@@ -0,0 +1,71 @@
1
+ /**
2
+ Copyright: 2022 Contrast Security, Inc
3
+ Contact: support@contrastsecurity.com
4
+ License: Commercial
5
+
6
+ NOTICE: This Software and the patented inventions embodied within may only be
7
+ used as part of Contrast Security’s commercial offerings. Even though it is
8
+ made available through public repositories, use of this Software is subject to
9
+ the applicable End User Licensing Agreement found at
10
+ https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
11
+ between Contrast Security and the End User. The Software may not be reverse
12
+ engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
+ way not consistent with the End User License Agreement.
14
+ */
15
+ 'use strict';
16
+
17
+ const t = require('@babel/types');
18
+
19
+ const IMPORT_META_URL_MEMBER_EXPRESSION = t.memberExpression(
20
+ t.memberExpression(t.identifier('import'), t.identifier('meta')),
21
+ t.identifier('url')
22
+ );
23
+
24
+ /**
25
+ * Appends calls to our own instrumentable import methods, providing access to
26
+ * the imported modules.
27
+ * ```
28
+ * import x from 'mod';
29
+ * // becomes:
30
+ * import x from 'mod';
31
+ * ContrastMethods.__importDefault(x, 'mod', import.meta.url);
32
+ *
33
+ * import * as x from 'mod';
34
+ * // becomes:
35
+ * import x from 'mod';
36
+ * ContrastMethods.__importNamespace(x, 'mod', import.meta.url);
37
+ *
38
+ * import { foo, bar as baz } from 'mod';;
39
+ * // becomes
40
+ * ContrastMethods.__import(foo, 'foo', 'mod', import.meta.url);
41
+ * ContrastMethods.__import(baz, 'bar', 'mod', import.meta.url);
42
+ * ```
43
+ * @param {import('@babel/traverse').NodePath<import('@babel/types').ImportDeclaration>} path
44
+ * @param {import('.').State} state
45
+ */
46
+ module.exports = function ImportDeclaration(path, state) {
47
+ const { source, specifiers } = path.node;
48
+
49
+ path.insertAfter(
50
+ specifiers.map((importSpec) => {
51
+ const spec = state.specs.find(({ type }) => type === importSpec.type);
52
+
53
+ if (!spec || !state.callees[spec.name]) return;
54
+
55
+ const args = [importSpec.local];
56
+
57
+ if (t.isImportSpecifier(importSpec)) {
58
+ args.push(
59
+ t.isIdentifier(importSpec.imported)
60
+ ? t.stringLiteral(importSpec.imported.name)
61
+ : importSpec.imported
62
+ );
63
+ }
64
+
65
+ args.push(source);
66
+ args.push(IMPORT_META_URL_MEMBER_EXPRESSION);
67
+
68
+ return t.callExpression(state.callees[spec.name], args);
69
+ })
70
+ );
71
+ };
@@ -18,23 +18,24 @@ const { default: generate } = require('@babel/generator');
18
18
  const { parse } = require('@babel/parser');
19
19
  const { default: traverse } = require('@babel/traverse');
20
20
 
21
+ const RewriteDeadzones = require('../../assess/deadzones/rewrite');
22
+ const { util: sourceMapUtility } = require('../../util/source-map');
21
23
  const Scopes = require('../async-storage/scopes');
22
24
  const logger = require('../logger')('contrast:rewrite');
23
- const RewriteDeadzones = require('../../assess/deadzones/rewrite');
24
- const logRewrite = require('./log');
25
- const RewriteLog = require('./rewrite-log');
26
- const isContrastMethod = require('./is-contrast-method');
27
- const functionWrap = require('./function-wrap');
28
- const prependGlobals = require('./prepend-globals');
29
25
  const AssignmentExpression = require('./assignment-expression');
30
26
  const BinaryExpression = require('./binary-expression');
31
27
  const CallExpression = require('./call-expression');
32
28
  const CatchClause = require('./catch-clause');
29
+ const functionWrap = require('./function-wrap');
30
+ const ImportDeclaration = require('./import-declaration');
31
+ const isContrastMethod = require('./is-contrast-method');
32
+ const logRewrite = require('./log');
33
33
  const MemberExpression = require('./member-expression');
34
34
  const ObjectProperty = require('./object-property');
35
+ const prependGlobals = require('./prepend-globals');
36
+ const RewriteLog = require('./rewrite-log');
35
37
  const SwitchStatement = require('./switch-statement');
36
38
  const TemplateLiteral = require('./template-literal');
37
- const sourceMapUtility = require('../../util/source-map').util;
38
39
 
39
40
  /**
40
41
  * @typedef {Object} State
@@ -105,6 +106,7 @@ class Rewriter {
105
106
  BinaryExpression,
106
107
  CallExpression,
107
108
  CatchClause,
109
+ ImportDeclaration,
108
110
  MemberExpression,
109
111
  ObjectProperty,
110
112
  SwitchStatement,
@@ -114,6 +116,7 @@ class Rewriter {
114
116
  null,
115
117
  initialState
116
118
  );
119
+ traverse.cache.clear();
117
120
  }
118
121
 
119
122
  /**
@@ -14,7 +14,6 @@ Copyright: 2022 Contrast Security, Inc
14
14
  */
15
15
  'use strict';
16
16
 
17
- const _ = require('lodash');
18
17
  const logger = require('../logger')('contrast:rewrite:injections');
19
18
  const patcher = require('../../hooks/patcher');
20
19
  const { PATCH_TYPES } = require('../../constants');
@@ -100,7 +99,11 @@ const ContrastMethods = new Injection(null, 'ContrastMethods', {
100
99
  },
101
100
  __contrastEval: function __contrastEval(str) {
102
101
  return str;
103
- }
102
+ },
103
+ // TODO: NODE-2020
104
+ __importDefault(mod, source, url) {},
105
+ __importNamespace(mod, source, url) {},
106
+ __import(mod, spec, source, url) {}
104
107
  });
105
108
 
106
109
  ContrastMethods.enable();
@@ -157,8 +160,7 @@ module.exports = {
157
160
  * @returns {Injection[]}
158
161
  */
159
162
  getEnabled() {
160
- return _.reduce(
161
- injections,
163
+ return Object.values(injections).reduce(
162
164
  (enabled, injection) =>
163
165
  injection.enabled() ? [...enabled, injection] : enabled,
164
166
  []
@@ -13,7 +13,6 @@ Copyright: 2022 Contrast Security, Inc
13
13
  way not consistent with the End User License Agreement.
14
14
  */
15
15
  'use strict';
16
- const _ = require('lodash');
17
16
 
18
17
  /**
19
18
  * Helper class that provides some means of optimizing the rewrite process.
@@ -32,11 +31,9 @@ module.exports = class RewriteLog {
32
31
  this._tokenMatches = specs.reduce(
33
32
  (matches, spec) =>
34
33
  callees[spec.name]
35
- ? _.set(
36
- matches,
37
- spec.name,
38
- !spec.token || 0 <= codeString.indexOf(spec.token)
39
- )
34
+ ? Object.assign(matches, {
35
+ [spec.name]: !spec.token || 0 <= codeString.indexOf(spec.token)
36
+ })
40
37
  : matches,
41
38
  {}
42
39
  );
@@ -60,7 +57,7 @@ module.exports = class RewriteLog {
60
57
  * if we need to even rewrite the code at all.
61
58
  */
62
59
  foundTokens() {
63
- return _.some(this._tokenMatches, _.identity);
60
+ return Object.values(this._tokenMatches).some(Boolean);
64
61
  }
65
62
 
66
63
  /**
@@ -72,6 +69,6 @@ module.exports = class RewriteLog {
72
69
  * make changes, we can just return original code.
73
70
  */
74
71
  rewritesOccurred() {
75
- return !this.aborted && _.some(this._tokensRewritten, _.identity);
72
+ return !this.aborted && Object.values(this._tokensRewritten).some(Boolean);
76
73
  }
77
74
  };
@@ -21,6 +21,8 @@ const {
21
21
  } = require('../../constants');
22
22
  const { emitSourceEvent } = require('../../hooks/frameworks/common');
23
23
  const agentEmitter = require('../../agent-emitter');
24
+ const patcher = require('../../hooks/patcher');
25
+ const { PATCH_TYPES } = require('../../constants');
24
26
  const {
25
27
  utils,
26
28
  constants: { EVENTS }
@@ -39,6 +41,39 @@ class RestifyProtectSources {
39
41
  EVENTS.CREATE_SERVER,
40
42
  this.registerUrlParamsHandler.bind(this)
41
43
  );
44
+ agentEmitter.on(
45
+ EVENTS.RESTIFY_EXPORT,
46
+ this.registerQueryParamsHandler.bind(this)
47
+ );
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Patches query parser middleware to wrap the callback argument. Once this
53
+ * wrapped callback is invoked w/out error we know we can proxy `req.query`.
54
+ * @param {object} restify
55
+ */
56
+ registerQueryParamsHandler(restify) {
57
+ const {
58
+ plugins: { queryParser: origQueryParser }
59
+ } = restify;
60
+
61
+ if (origQueryParser) {
62
+ patcher.patch(restify.plugins, 'queryParser', {
63
+ name: 'restify.plugins',
64
+ patchType: PATCH_TYPES.FRAMEWORK,
65
+ alwaysRun: true,
66
+ post(data) {
67
+ patcher.patch(data, 'result', {
68
+ name: 'restify.plugins.queryParser',
69
+ patchType: PATCH_TYPES.PROTECT_SOURCE,
70
+ alwaysRun: true,
71
+ post(data) {
72
+ decorateRequest({ query: get(data.args[0], 'query') });
73
+ }
74
+ });
75
+ }
76
+ });
42
77
  }
43
78
  }
44
79
 
@@ -26,9 +26,11 @@ const brackets = /\[(.{1,1024}?)\]/;
26
26
  const child = /\[(.{1,1024}?)\]/g;
27
27
 
28
28
  const MONGODB = 'mongodb';
29
+ const RETHINKDB = 'rethinkdb';
29
30
 
30
31
  const ScannerKit = new Map([
31
- [MONGODB, () => require('../nosqli/nosql-scanner').create('MongoDB')]
32
+ [MONGODB, () => require('../nosqli/nosql-scanner').create('MongoDB')],
33
+ [RETHINKDB, () => require('../nosqli/nosql-scanner').create('RethinkDB')]
32
34
  ]);
33
35
  const SubstringFinder = require('../base-scanner/substring-finder');
34
36
 
@@ -144,27 +146,14 @@ class NoSqlInjectionRule extends require('../') {
144
146
  _documentType === constants.INPUT_TYPES.PARAMETER_NAME &&
145
147
  _documentPath.length <= 1024
146
148
  ) {
147
- let segment = brackets.exec(_documentPath);
148
- const parent = segment
149
- ? _documentPath.slice(0, segment.index)
150
- : _documentPath;
151
-
152
- pathArray.push('query');
153
-
154
- if (parent) {
155
- pathArray.push(parent);
156
- }
157
- while ((segment = child.exec(_documentPath))) {
158
- pathArray.push(segment[1]);
159
- }
160
- pathArray.pop();
149
+ this.buildPathArray(_documentPath, pathArray);
161
150
  } else {
162
151
  // only qs params and body are "expandable"
163
152
  pathArray.push('body', ..._documentPath.split('.'));
164
153
  }
165
154
 
166
155
  let data;
167
- let curr = ctx.req;
156
+ let curr = ctx.request;
168
157
 
169
158
  for (const path of pathArray) {
170
159
  if (curr) {
@@ -175,6 +164,31 @@ class NoSqlInjectionRule extends require('../') {
175
164
  return data;
176
165
  }
177
166
 
167
+ buildPathArray(documentPath, pathArray) {
168
+ const documentPathArray = documentPath.split('.');
169
+
170
+ pathArray.push('query');
171
+ documentPathArray.forEach((dotSegment) => {
172
+ let lastChar;
173
+ let bracketSegment = brackets.exec(dotSegment);
174
+ let parent = bracketSegment
175
+ ? dotSegment.slice(0, bracketSegment.index)
176
+ : dotSegment;
177
+ if (parent) {
178
+ lastChar = parent.slice(-1);
179
+ parent = lastChar === ']' ? parent.slice(0, -1) : parent;
180
+ pathArray.push(parent);
181
+ }
182
+ while ((bracketSegment = child.exec(dotSegment))) {
183
+ lastChar = bracketSegment[1].slice(-1);
184
+ const segment =
185
+ lastChar === ']' ? bracketSegment[1].slice(0, -1) : bracketSegment[1];
186
+ pathArray.push(segment);
187
+ }
188
+ });
189
+ pathArray.pop();
190
+ }
191
+
178
192
  getScanner(id) {
179
193
  if (!ScannerKit.has(id)) {
180
194
  throw new Error(`Unknown NoSQL scanner: ${id}`);
@@ -33,7 +33,7 @@ module.exports = {
33
33
 
34
34
  const databases = {
35
35
  MongoDB: () => new (require('./mongodbscanner'))(options),
36
-
36
+ RethinkDB: () => new (require('./rethinkdbscanner'))(options),
37
37
  [ERROR_KEY]: () => {
38
38
  throw new Error();
39
39
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ Copyright: 2022 Contrast Security, Inc
3
+ Contact: support@contrastsecurity.com
4
+ License: Commercial
5
+
6
+ NOTICE: This Software and the patented inventions embodied within may only be
7
+ used as part of Contrast Security’s commercial offerings. Even though it is
8
+ made available through public repositories, use of this Software is subject to
9
+ the applicable End User Licensing Agreement found at
10
+ https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
11
+ between Contrast Security and the End User. The Software may not be reverse
12
+ engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
+ way not consistent with the End User License Agreement.
14
+ */
15
+ /**
16
+ * RethinkDB scanner module
17
+ * @module lib/protect/rules/nosql/nosql-scanner/RethinkDBScanner
18
+ */
19
+
20
+ 'use strict';
21
+
22
+ const { BaseScanner } = require('../../base-scanner');
23
+
24
+ class RethinkDBScanner extends BaseScanner {}
25
+
26
+ module.exports = RethinkDBScanner;
@@ -29,6 +29,7 @@ const MongoDBSink = require('./mongodb');
29
29
  const MySQLSink = require('./mysql');
30
30
  const NodeSerializeSink = require('./node-serialize');
31
31
  const PostgresSink = require('./postgres');
32
+ const RethinkDBSink = require('./rethinkdb');
32
33
  const SequelizeSink = require('./sequelize');
33
34
  const Sqlite3Sink = require('./sqlite3');
34
35
  const VMSink = require('./vm');
@@ -46,6 +47,7 @@ module.exports = function init(agent) {
46
47
  new MySQLSink(agent).install({ ModuleHook });
47
48
  new NodeSerializeSink(agent).install({ ModuleHook });
48
49
  new PostgresSink(agent).install({ ModuleHook });
50
+ new RethinkDBSink(agent).install({ ModuleHook });
49
51
  new SequelizeSink(agent).install({ ModuleHook });
50
52
  new VMSink(agent).install({ ModuleHook });
51
53
  new Sqlite3Sink(agent).install({ ModuleHook });
@@ -21,8 +21,6 @@ const BaseSensor = require('../../hooks/frameworks/base');
21
21
  const patcher = require('../../hooks/patcher');
22
22
  const { PATCH_TYPES } = require('../../constants');
23
23
  const { emitSinkEvent } = require('../../hooks/frameworks/common');
24
- const agentEmitter = require('../../agent-emitter');
25
- const SinkEvent = require('../models/sink-event');
26
24
 
27
25
  const { SINK_TYPES } = constants;
28
26
  const ID = 'mongodb';
@@ -37,7 +35,7 @@ function getCursorQueryData(args, version) {
37
35
  }
38
36
 
39
37
  if (_.isString(query)) {
40
- return query.toString()
38
+ return query.toString();
41
39
  }
42
40
 
43
41
  if (query['$where']) {
@@ -0,0 +1,47 @@
1
+ /**
2
+ Copyright: 2022 Contrast Security, Inc
3
+ Contact: support@contrastsecurity.com
4
+ License: Commercial
5
+
6
+ NOTICE: This Software and the patented inventions embodied within may only be
7
+ used as part of Contrast Security’s commercial offerings. Even though it is
8
+ made available through public repositories, use of this Software is subject to
9
+ the applicable End User Licensing Agreement found at
10
+ https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
11
+ between Contrast Security and the End User. The Software may not be reverse
12
+ engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
+ way not consistent with the End User License Agreement.
14
+ */
15
+ 'use strict';
16
+
17
+ const constants = require('../../constants');
18
+ const BaseSensor = require('../../hooks/frameworks/base');
19
+ const patcher = require('../../hooks/patcher');
20
+ const { PATCH_TYPES } = require('../../constants');
21
+ const { emitSinkEvent } = require('../../hooks/frameworks/common');
22
+
23
+ const { SINK_TYPES } = constants;
24
+ const ID = 'rethinkdb';
25
+
26
+ class RethinkDBSensor extends BaseSensor {
27
+ constructor(agent) {
28
+ super({ id: ID, agent });
29
+ }
30
+
31
+ install({ ModuleHook }) {
32
+ ModuleHook.resolve({ name: 'rethinkdb' }, (rethinkdb) => {
33
+ patcher.patch(rethinkdb, 'js', {
34
+ alwaysRun: true,
35
+ name: 'rethinkdb',
36
+ patchType: PATCH_TYPES.PROTECT_SINK,
37
+ pre: (data) => {
38
+ emitSinkEvent(data.args[0], SINK_TYPES.NOSQL_QUERY, ID);
39
+ }
40
+ });
41
+ });
42
+
43
+ return this;
44
+ }
45
+ }
46
+
47
+ module.exports = RethinkDBSensor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/agent",
3
- "version": "4.9.1",
3
+ "version": "4.10.3",
4
4
  "description": "Node.js security instrumentation by Contrast Security",
5
5
  "keywords": [
6
6
  "security",
@@ -19,7 +19,13 @@
19
19
  "Griffin Yourick",
20
20
  "Ati Ok",
21
21
  "Pat McClory",
22
- "Michael Woytowitz"
22
+ "Michael Woytowitz",
23
+ "Jacob Kaplan",
24
+ "Yulia Tenincheva",
25
+ "Bruce MacNaughton",
26
+ "Krasen Penchev",
27
+ "Ivaylo Grahlyov",
28
+ "Yavor Stoychev"
23
29
  ],
24
30
  "scripts": {
25
31
  "docs": "jsdoc -c ../.jsdoc.json",
@@ -72,10 +78,10 @@
72
78
  "@babel/types": "^7.12.1",
73
79
  "@contrast/distringuish-prebuilt": "^2.2.0",
74
80
  "@contrast/flat": "^4.1.1",
75
- "@contrast/fn-inspect": "^2.4.3",
81
+ "@contrast/fn-inspect": "^2.4.4",
76
82
  "@contrast/heapdump": "^1.1.0",
77
- "@contrast/protobuf-api": "^3.2.0",
78
- "@contrast/require-hook": "^2.0.6",
83
+ "@contrast/protobuf-api": "^3.2.3",
84
+ "@contrast/require-hook": "^2.0.8",
79
85
  "@contrast/synchronous-source-maps": "^1.1.0",
80
86
  "amqp-connection-manager": "^3.2.2",
81
87
  "amqplib": "^0.8.0",
@@ -107,12 +113,14 @@
107
113
  "devDependencies": {
108
114
  "@aws-sdk/client-dynamodb": "^3.39.0",
109
115
  "@bmacnaughton/string-generator": "^1.0.0",
110
- "@contrast/eslint-config": "^2.0.1",
116
+ "@contrast/eslint-config": "^2.2.0",
111
117
  "@contrast/fake-module": "file:test/mock/contrast-fake",
112
- "@contrast/screener-service": "^1.12.8",
118
+ "@contrast/screener-service": "^1.12.9",
113
119
  "@hapi/boom": "file:test/mock/boom",
114
120
  "@hapi/hapi": "file:test/mock/hapi",
115
121
  "@ls-lint/ls-lint": "^1.8.1",
122
+ "@typescript-eslint/eslint-plugin": "^5.10.2",
123
+ "@typescript-eslint/parser": "^5.10.2",
116
124
  "ajv": "^8.5.0",
117
125
  "ast-types": "^0.12.4",
118
126
  "aws-sdk": "file:test/mock/aws-sdk",
@@ -129,11 +137,11 @@
129
137
  "dustjs-linkedin": "^3.0.1",
130
138
  "ejs": "^3.1.6",
131
139
  "escape-html": "^1.0.3",
132
- "eslint": "^8.2.0",
133
- "eslint-config-prettier": "^6.11.0",
134
- "eslint-plugin-mocha": "^7.0.1",
140
+ "eslint": "^8.8.0",
141
+ "eslint-config-prettier": "^8.3.0",
142
+ "eslint-plugin-mocha": "^10.0.3",
135
143
  "eslint-plugin-node": "^11.1.0",
136
- "eslint-plugin-prettier": "^3.1.4",
144
+ "eslint-plugin-prettier": "^4.0.0",
137
145
  "express": "file:test/mock/express",
138
146
  "fetch-cookie": "^0.11.0",
139
147
  "form-data": "^3.0.0",
@@ -142,13 +150,13 @@
142
150
  "husky": "^6.0.0",
143
151
  "inquirer": "^8.1.2",
144
152
  "joi": "^17.4.0",
145
- "jsdoc": "^3.6.7",
153
+ "jsdoc": "^3.6.10",
146
154
  "libxmljs": "file:test/mock/libxmljs",
147
155
  "libxmljs2": "file:test/mock/libxmljs2",
148
156
  "lint-staged": "^12.0.2",
149
157
  "madge": "^4.0.1",
150
158
  "marsdb": "file:test/mock/marsdb",
151
- "mocha": "^9.1.3",
159
+ "mocha": "^9.2.0",
152
160
  "mochawesome": "^7.0.1",
153
161
  "mongodb": "file:test/mock/mongodb",
154
162
  "mongodb-npm": "npm:mongodb@^3.6.5",
@@ -156,13 +164,13 @@
156
164
  "mustache": "^3.0.1",
157
165
  "mysql": "file:test/mock/mysql",
158
166
  "nock": "^12.0.3",
159
- "node-fetch": "^2.6.1",
167
+ "node-fetch": "^2.6.7",
160
168
  "node-serialize": "file:test/mock/node-serialize",
161
169
  "npm-license-crawler": "^0.2.1",
162
170
  "nyc": "^15.1.0",
163
171
  "pg": "file:test/mock/pg",
164
172
  "pino": "^6.7.0",
165
- "prettier": "^1.19.1",
173
+ "prettier": "^2.5.1",
166
174
  "proxyquire": "^2.1.0",
167
175
  "qs": "^6.9.4",
168
176
  "rethinkdb": "file:test/mock/rethinkdb",