@contrast/assess 1.29.1 → 1.30.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.
@@ -24,18 +24,30 @@ const { InstrumentationType: { RULE } } = require('../../constants');
24
24
  const { PATCH_TYPE: patchType } = require('../common');
25
25
 
26
26
  const SAFE_HASH_ALGORITHMS = new Set([
27
- 'RSA-SHA1-2',
28
- 'RSA-SHA224',
29
- 'RSA-SHA256',
30
- 'RSA-SHA384',
31
- 'RSA-SHA512',
27
+ // SHA224
28
+ 'rsa-sha224',
29
+ 'sha-224',
30
+ 'sha2-224',
32
31
  'sha224',
33
- 'sha224WithRSAEncryption',
32
+ 'sha224withrsaencryption',
33
+ // SHA256
34
+ 'rsa-sha256',
35
+ 'sha-256',
36
+ 'sha2-256',
34
37
  'sha256',
35
- 'sha256WithRSAEncryption',
38
+ 'sha256withrsaencryption',
39
+ // SHA384
40
+ 'rsa-sha384',
41
+ 'sha-384',
42
+ 'sha2-384',
36
43
  'sha384',
37
- 'sha384WithRSAEncryption',
38
- 'sha512'
44
+ 'sha384withrsaencryption',
45
+ // SHA512
46
+ 'rsa-sha512',
47
+ 'sha-512',
48
+ 'sha2-512',
49
+ 'sha512',
50
+ 'sha512withrsaencryption',
39
51
  ]);
40
52
  const SAFE_HASH_LIBS = ['etag', 'browserify', 'deps-sort'];
41
53
  const SAFE_CIPHER_ALGORITHM_PREFIXES = ['des-ede', 'id-aes', 'aes', 'rsa'];
@@ -53,7 +65,6 @@ module.exports = function (core) {
53
65
  logger,
54
66
  patcher,
55
67
  assess: {
56
- inspect, // todo: remove
57
68
  eventFactory,
58
69
  cryptoAnalysis,
59
70
  getSourceContext,
@@ -68,16 +79,14 @@ module.exports = function (core) {
68
79
  patchType,
69
80
  post(data) {
70
81
  const [alg] = data.args;
82
+ if (!isString(alg) || !getSourceContext(RULE, Rule.CRYPTO_BAD_MAC)) return;
71
83
 
72
- if (
73
- !isString(alg) ||
74
- !getSourceContext(RULE, Rule.CRYPTO_BAD_MAC) ||
75
- SAFE_HASH_ALGORITHMS.has(alg)
76
- ) return;
84
+ const algLower = StringPrototypeToLowerCase.call(alg);
85
+ if (SAFE_HASH_ALGORITHMS.has(algLower)) return;
77
86
 
78
87
  const event = eventFactory.createCryptoAnalysisEvent({
79
88
  args: [{ tracked: false, value: alg }],
80
- context: `crypto.createHash(${inspect(alg)})`,
89
+ context: `crypto.createHash(${algLower})`,
81
90
  methodName: 'createHash',
82
91
  moduleName: 'crypto',
83
92
  name: 'crypto.createHash',
@@ -130,7 +139,7 @@ module.exports = function (core) {
130
139
 
131
140
  const event = eventFactory.createCryptoAnalysisEvent({
132
141
  args: [{ tracked: false, value: alg }],
133
- context: `crypto.${method}(${inspect(alg)})`,
142
+ context: `crypto.${method}(${algLower})`,
134
143
  methodName: method,
135
144
  moduleName: 'crypto',
136
145
  name: `crypto.${method}`,
@@ -77,11 +77,13 @@ module.exports = function(core) {
77
77
  WEAK_URL_ENCODED,
78
78
  ];
79
79
 
80
- const preHook = (name, method) => (data) => {
80
+ const preHook = (moduleName, responseName, method) => ({ args, obj: response, result, hooked, orig }) => {
81
+ const methodName = `${responseName + (moduleName !== 'spdy' ? '.prototype' : '')}.${method}`;
82
+ const name = `${moduleName}.${methodName}`;
81
83
  const sourceContext = getSourceContext(RULE, ruleId);
82
84
  if (!sourceContext) return;
83
85
 
84
- const payload = data.args[0];
86
+ const payload = args[0];
85
87
  if (!payload) return;
86
88
 
87
89
  const strInfo = tracker.getData(payload);
@@ -90,6 +92,7 @@ module.exports = function(core) {
90
92
  const { contentType } = sourceContext.responseData;
91
93
  if (contentType && isSafeContentType(contentType)) return;
92
94
 
95
+ if (moduleName === 'spdy') response.spdyStream.once('finish', () => response.emit('finish'));
93
96
  if (isVulnerable(UNTRUSTED, safeTags, strInfo.tags)) {
94
97
  const event = createSinkEvent({
95
98
  args: [{
@@ -99,20 +102,20 @@ module.exports = function(core) {
99
102
  context: `res.${method}('${strInfo.value}')`,
100
103
  history: [strInfo],
101
104
  name,
102
- moduleName: 'http',
103
- methodName: `ServerResponse.prototype.${method}`,
105
+ moduleName,
106
+ methodName,
104
107
  object: {
105
108
  tracked: false,
106
- value: 'http.ServerResponse'
109
+ value: `${moduleName}.${responseName}`
107
110
  },
108
111
  result: {
109
- value: data.result,
112
+ value: result,
110
113
  tracked: false,
111
114
  },
112
115
  source: 'P0',
113
116
  stacktraceOpts: {
114
- constructorOpt: data.hooked,
115
- prependFrames: [data.orig]
117
+ constructorOpt: hooked,
118
+ prependFrames: [orig]
116
119
  },
117
120
  tags: strInfo.tags,
118
121
  });
@@ -139,21 +142,47 @@ module.exports = function(core) {
139
142
  http.install = function() {
140
143
  depHooks.resolve({ name: 'http' }, (http) => {
141
144
  {
142
- const name = 'http.ServerResponse.prototype.write';
143
145
  const method = 'write';
144
146
  patcher.patch(http.ServerResponse.prototype, method, {
145
- name,
147
+ name: 'http.ServerResponse.prototype.write',
146
148
  patchType,
147
- pre: preHook(name, method),
149
+ pre: preHook('http', 'ServerResponse', method),
148
150
  });
149
151
  }
150
152
  {
151
- const name = 'http.ServerResponse.prototype.end';
152
153
  const method = 'end';
153
154
  patcher.patch(http.ServerResponse.prototype, method, {
154
- name,
155
+ name: 'http.ServerResponse.prototype.end',
155
156
  patchType,
156
- pre: preHook(name, method),
157
+ pre: preHook('http', 'ServerResponse', method),
158
+ });
159
+ }
160
+ });
161
+ depHooks.resolve({ name: 'http2' }, (http2) => {
162
+ {
163
+ const method = 'write';
164
+ patcher.patch(http2.Http2ServerResponse.prototype, method, {
165
+ name: 'http2.Http2ServerResponse.prototype.write',
166
+ patchType,
167
+ pre: preHook('http2', 'Http2ServerResponse', method),
168
+ });
169
+ }
170
+ {
171
+ const method = 'end';
172
+ patcher.patch(http2.Http2ServerResponse.prototype, method, {
173
+ name: 'http2.Http2ServerResponse.prototype.end',
174
+ patchType,
175
+ pre: preHook('http2', 'Http2ServerResponse', method),
176
+ });
177
+ }
178
+ });
179
+ depHooks.resolve({ name: 'spdy', file: 'lib/spdy/response.js' }, (response) => {
180
+ {
181
+ const method = 'end';
182
+ patcher.patch(response, method, {
183
+ name: 'spdy.response.end',
184
+ patchType,
185
+ pre: preHook('spdy', 'response', method),
157
186
  });
158
187
  }
159
188
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/assess",
3
- "version": "1.29.1",
3
+ "version": "1.30.0",
4
4
  "description": "Contrast service providing framework-agnostic Assess support",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
@@ -17,7 +17,7 @@
17
17
  "test": "../scripts/test.sh"
18
18
  },
19
19
  "dependencies": {
20
- "@contrast/common": "1.21.2",
20
+ "@contrast/common": "1.21.3",
21
21
  "@contrast/distringuish": "^5.0.0",
22
22
  "@contrast/scopes": "1.4.1"
23
23
  }