@contrast/agent 4.12.1 → 4.13.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 (57) hide show
  1. package/bootstrap.js +2 -3
  2. package/esm.mjs +9 -35
  3. package/lib/assess/membrane/debraner.js +0 -2
  4. package/lib/assess/membrane/index.js +1 -3
  5. package/lib/assess/models/base-event.js +1 -1
  6. package/lib/assess/models/tag-range/util.js +1 -2
  7. package/lib/assess/policy/util.js +3 -2
  8. package/lib/assess/propagators/JSON/stringify.js +6 -11
  9. package/lib/assess/propagators/ajv/conditionals.js +0 -3
  10. package/lib/assess/propagators/ajv/json-schema-type-evaluators.js +5 -4
  11. package/lib/assess/propagators/ajv/refs.js +1 -2
  12. package/lib/assess/propagators/ajv/schema-context.js +2 -3
  13. package/lib/assess/propagators/path/common.js +38 -29
  14. package/lib/assess/propagators/path/resolve.js +1 -0
  15. package/lib/assess/propagators/sequelize/utils.js +1 -2
  16. package/lib/assess/propagators/v8/init-hooks.js +0 -1
  17. package/lib/assess/sinks/dynamo.js +65 -30
  18. package/lib/assess/static/hardcoded.js +3 -3
  19. package/lib/assess/static/read-findings-from-cache.js +40 -0
  20. package/lib/assess/technologies/index.js +12 -13
  21. package/lib/cli-rewriter/index.js +65 -6
  22. package/lib/core/config/options.js +6 -0
  23. package/lib/core/config/util.js +15 -33
  24. package/lib/core/exclusions/input.js +6 -1
  25. package/lib/core/express/index.js +2 -4
  26. package/lib/core/logger/debug-logger.js +2 -2
  27. package/lib/core/stacktrace.js +2 -1
  28. package/lib/hooks/http.js +81 -81
  29. package/lib/hooks/require.js +1 -0
  30. package/lib/instrumentation.js +17 -0
  31. package/lib/protect/analysis/aho-corasick.js +1 -1
  32. package/lib/protect/errors/handler-async-errors.js +66 -0
  33. package/lib/protect/input-analysis.js +7 -13
  34. package/lib/protect/listeners.js +27 -23
  35. package/lib/protect/rules/base-scanner/index.js +2 -2
  36. package/lib/protect/rules/bot-blocker/bot-blocker-rule.js +4 -2
  37. package/lib/protect/rules/cmd-injection/cmdinjection-rule.js +57 -2
  38. package/lib/protect/rules/cmd-injection-semantic-chained-commands/cmd-injection-semantic-chained-commands-rule.js +31 -2
  39. package/lib/protect/rules/cmd-injection-semantic-dangerous-paths/cmd-injection-semantic-dangerous-paths-rule.js +32 -2
  40. package/lib/protect/rules/index.js +42 -21
  41. package/lib/protect/rules/ip-denylist/ip-denylist-rule.js +2 -2
  42. package/lib/protect/rules/nosqli/nosql-injection-rule.js +104 -39
  43. package/lib/protect/rules/path-traversal/path-traversal-rule.js +3 -0
  44. package/lib/protect/rules/rule-factory.js +6 -7
  45. package/lib/protect/rules/signatures/signature.js +3 -0
  46. package/lib/protect/rules/sqli/sql-injection-rule.js +98 -5
  47. package/lib/protect/rules/sqli/sql-scanner/labels.json +0 -3
  48. package/lib/protect/rules/xss/reflected-xss-rule.js +3 -3
  49. package/lib/protect/sample-aggregator.js +65 -57
  50. package/lib/protect/service.js +709 -104
  51. package/lib/reporter/models/app-activity/sample.js +6 -0
  52. package/lib/reporter/speedracer/unknown-connection-state.js +20 -32
  53. package/lib/reporter/translations/to-protobuf/settings/assess-features.js +4 -6
  54. package/lib/reporter/ts-reporter.js +1 -1
  55. package/lib/util/get-file-type.js +43 -0
  56. package/package.json +10 -11
  57. package/perf-logs.js +2 -5
@@ -39,6 +39,12 @@ class Sample {
39
39
  this.input = input;
40
40
  this.request = appContext.request;
41
41
 
42
+ // extra info for processing at sink time.
43
+ // NOT TO BE INCLUDED IN ACTUAL DTM AT REPORTING TIME.
44
+ // This is particularly useful when using the agent lib for processing
45
+ // mongo expansion and injection.
46
+ this._inputInfoForSink = {};
47
+
42
48
  this.assessment = assessment;
43
49
 
44
50
  if (assessment) {
@@ -46,28 +46,23 @@ class UnknownConnectionState extends BaseConnectionState {
46
46
  * @param {SpeedracerBaseMessage} message
47
47
  * @returns {Promise}
48
48
  */
49
- send(message) {
50
- const { speedracer } = this;
51
- return new Promise(async (resolve, reject) => {
49
+ async send(message) {
50
+ try {
51
+ const clientResponse = await super.send(message);
52
+ this.speedracer.transitionConnectionState(SUCCESS);
53
+ return clientResponse;
54
+ } catch (err) {
55
+ // See if we need to start or wait for service
52
56
  try {
53
- const clientResponse = await super.send(message);
54
- speedracer.transitionConnectionState(SUCCESS);
55
- resolve(clientResponse);
57
+ await this.handleSendFailure(err);
58
+ await this.retryInitialization();
59
+ const result = await this.speedracer.send(message);
60
+ return result;
56
61
  } catch (err) {
57
- // See if we need to start or wait for service
58
- try {
59
- await this.handleSendFailure(err);
60
- await this.retryInitialization();
61
- // eslint-disable-next-line prettier/prettier
62
- speedracer.send(message)
63
- .then((r) => resolve(r))
64
- .catch((e) => reject(e));
65
- } catch (err) {
66
- speedracer.transitionConnectionState(FAILURE);
67
- reject(err);
68
- }
62
+ this.speedracer.transitionConnectionState(FAILURE);
63
+ throw err;
69
64
  }
70
- });
65
+ }
71
66
  }
72
67
 
73
68
  /**
@@ -106,25 +101,18 @@ class UnknownConnectionState extends BaseConnectionState {
106
101
  * messages.
107
102
  * @returns {Promise}
108
103
  */
109
- retryInitialization() {
104
+ async retryInitialization() {
110
105
  const startup = this.speedracer.messageCache.get('startup');
111
106
  const appcreate = this.speedracer.messageCache.get('appcreate');
112
107
 
113
108
  if (!startup || !appcreate) return Promise.resolve();
114
109
 
115
- return new Promise(async (resolve, reject) => {
116
- this.speedracer.logger.debug(
117
- 'Sending initialization messages to service'
118
- );
110
+ this.speedracer.logger.debug(
111
+ 'Sending initialization messages to service'
112
+ );
119
113
 
120
- try {
121
- await this.speedracer.send(startup);
122
- await this.speedracer.send(appcreate);
123
- resolve();
124
- } catch (err) {
125
- reject(err);
126
- }
127
- });
114
+ await this.speedracer.send(startup);
115
+ await this.speedracer.send(appcreate);
128
116
  }
129
117
 
130
118
  /**
@@ -36,7 +36,6 @@ function AssessFeatures({
36
36
  validatorScopes,
37
37
  validators = []
38
38
  } = {}) {
39
- /* eslint-disable no-sparse-arrays, prettier/prettier */
40
39
  return new settings.AssessFeatures([
41
40
  enabled, // 1 enabled
42
41
  dynamicSources, // 2 dynamic_sources
@@ -52,13 +51,12 @@ function AssessFeatures({
52
51
  validators.map(CustomRuleFeature).map(v => v.array), // 12 validators
53
52
  disabledRules, // 13 disabled_rules (deprecated)
54
53
  Sampling(sampling).array, // 14 sampling
55
- , // 15 -
56
- , // 16 -
57
- , // 17 -
58
- , // 18 -
54
+ undefined, // 15 -
55
+ undefined, // 16 -
56
+ undefined, // 17 -
57
+ undefined, // 18 -
59
58
  [] // 19 dynamic_sources_map
60
59
  ]);
61
- /* eslint-enable */
62
60
  }
63
61
 
64
62
  function AssessStacktrace(stacktraces) {
@@ -386,7 +386,7 @@ module.exports = class TSReporter {
386
386
  }
387
387
 
388
388
  if (!context) {
389
- logger.warn(`StorageContext unavailable - unable to send 'Activity'`);
389
+ logger.warn('StorageContext unavailable - sendActivityMessage() failed');
390
390
  return;
391
391
  }
392
392
 
@@ -0,0 +1,43 @@
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 path = require('path');
18
+ const parent = require('parent-package-json');
19
+
20
+ // eslint-disable-next-line complexity
21
+ function getType(filename) {
22
+ if (filename.startsWith('node:')) {
23
+ return 'builtin';
24
+ }
25
+ filename = filename.replace('file://', '');
26
+
27
+ let parentType = 'commonjs';
28
+ try {
29
+ parentType = parent(filename).parse().type;
30
+ } catch (err) {
31
+ // Node assumes `commonjs ` if there's no `type` set in package.json
32
+ }
33
+
34
+ const ext = path.extname(filename);
35
+ if (ext === '.mjs' || (ext === '.js' && parentType === 'module')) {
36
+ return 'module';
37
+ } else if (ext === '.cjs' || (ext === '.js' && parentType !== 'module')) {
38
+ return 'commonjs';
39
+ }
40
+ return 'unknown';
41
+ }
42
+
43
+ module.exports = getType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/agent",
3
- "version": "4.12.1",
3
+ "version": "4.13.1",
4
4
  "description": "Node.js security instrumentation by Contrast Security",
5
5
  "keywords": [
6
6
  "security",
@@ -29,8 +29,8 @@
29
29
  ],
30
30
  "scripts": {
31
31
  "docs": "jsdoc -c ../.jsdoc.json",
32
- "release": "scripts/make-release.js",
33
- "tag": "scripts/tag-release.js",
32
+ "release": "node scripts/make-release.js",
33
+ "tag": "node scripts/tag-release.js",
34
34
  "test:debug": "scripts/test.sh debug",
35
35
  "test": "scripts/test.sh",
36
36
  "test:screener": "mocha --parallel test/screener/**/*test.js",
@@ -76,12 +76,13 @@
76
76
  "@babel/template": "^7.10.4",
77
77
  "@babel/traverse": "^7.12.1",
78
78
  "@babel/types": "^7.12.1",
79
+ "@contrast/agent-lib": "^2.2.3",
79
80
  "@contrast/distringuish-prebuilt": "^2.2.0",
80
81
  "@contrast/flat": "^4.1.1",
81
82
  "@contrast/fn-inspect": "^2.4.4",
82
83
  "@contrast/heapdump": "^1.1.0",
83
84
  "@contrast/protobuf-api": "^3.2.3",
84
- "@contrast/require-hook": "^2.0.10",
85
+ "@contrast/require-hook": "^3.0.0",
85
86
  "@contrast/synchronous-source-maps": "^1.1.0",
86
87
  "amqp-connection-manager": "^3.2.2",
87
88
  "amqplib": "^0.8.0",
@@ -116,14 +117,14 @@
116
117
  "devDependencies": {
117
118
  "@aws-sdk/client-dynamodb": "^3.39.0",
118
119
  "@bmacnaughton/string-generator": "^1.0.0",
119
- "@contrast/eslint-config": "^3.0.0-beta.4",
120
+ "@contrast/eslint-config": "^3.0.0",
120
121
  "@contrast/fake-module": "file:test/mock/contrast-fake",
121
122
  "@contrast/screener-service": "^1.12.9",
122
123
  "@hapi/boom": "file:test/mock/boom",
123
124
  "@hapi/hapi": "file:test/mock/hapi",
124
125
  "@ls-lint/ls-lint": "^1.8.1",
125
- "@typescript-eslint/eslint-plugin": "^5.12.0",
126
- "@typescript-eslint/parser": "^5.12.0",
126
+ "@typescript-eslint/eslint-plugin": "^5.12.1",
127
+ "@typescript-eslint/parser": "^5.12.1",
127
128
  "ajv": "^8.5.0",
128
129
  "ast-types": "^0.12.4",
129
130
  "aws-sdk": "file:test/mock/aws-sdk",
@@ -141,10 +142,8 @@
141
142
  "ejs": "^3.1.6",
142
143
  "escape-html": "^1.0.3",
143
144
  "eslint": "^8.9.0",
144
- "eslint-config-prettier": "^8.3.0",
145
145
  "eslint-plugin-mocha": "^10.0.3",
146
146
  "eslint-plugin-node": "^11.1.0",
147
- "eslint-plugin-prettier": "^4.0.0",
148
147
  "express": "file:test/mock/express",
149
148
  "fetch-cookie": "^0.11.0",
150
149
  "form-data": "^3.0.0",
@@ -161,6 +160,7 @@
161
160
  "marsdb": "file:test/mock/marsdb",
162
161
  "mocha": "^9.2.0",
163
162
  "mochawesome": "^7.0.1",
163
+ "mock-fs": "^5.1.2",
164
164
  "mongodb": "file:test/mock/mongodb",
165
165
  "mongodb-npm": "npm:mongodb@^3.6.5",
166
166
  "mongoose": "^6.1.1",
@@ -173,13 +173,12 @@
173
173
  "nyc": "^15.1.0",
174
174
  "pg": "file:test/mock/pg",
175
175
  "pino": "^6.7.0",
176
- "prettier": "^2.5.1",
177
176
  "proxyquire": "^2.1.0",
178
177
  "qs": "^6.9.4",
179
178
  "rethinkdb": "file:test/mock/rethinkdb",
180
179
  "sequelize": "^6.11.0",
181
180
  "shellcheck": "^1.0.0",
182
- "sinon": "^7.2.2",
181
+ "sinon": "^9.2.4",
183
182
  "sinon-chai": "^3.3.0",
184
183
  "sqlite3": "file:test/mock/sqlite3",
185
184
  "swig": "file:test/mock/swig",
package/perf-logs.js CHANGED
@@ -104,7 +104,6 @@ async function processFile(filename, filter, group) {
104
104
  continue;
105
105
  }
106
106
  if (!group) {
107
- // eslint-disable-next-line no-console
108
107
  console.log(JSON.stringify(data, null, 4));
109
108
  } else {
110
109
  const key = filter
@@ -125,7 +124,6 @@ async function processFile(filename, filter, group) {
125
124
  }
126
125
 
127
126
  if (group) {
128
- // eslint-disable-next-line no-console
129
127
  console.log(JSON.stringify(Object.values(merged), null, 4));
130
128
  }
131
129
  }
@@ -148,10 +146,9 @@ if (program.filter) {
148
146
  try {
149
147
  filterRegex = new RegExp(program.filter);
150
148
  } catch (e) {
151
- // eslint-disable-next-line no-console
152
149
  console.error('invalid filter regex');
153
- // eslint-disable-next-line no-process-exit
154
- process.exit(-1);
150
+ process.exit(-1); // eslint-disable-line no-process-exit
151
+
155
152
  }
156
153
  }
157
154