@contrast/assess 1.65.0 → 1.67.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.
@@ -39,7 +39,7 @@ module.exports = function (core) {
39
39
  const apolloServer = core.assess.configurationAnalysis.apolloServer = {};
40
40
 
41
41
  apolloServer.install = function () {
42
- return depHooks.resolve({ name: '@apollo/server', version: '>=4', file: 'dist/cjs' }, (xport) => {
42
+ return depHooks.resolve({ name: '@apollo/server', version: '>=4' }, (xport) => {
43
43
  if (!xport.ApolloServer) return;
44
44
  patcher.patch(xport, 'ApolloServer', {
45
45
  name: '@apollo/server.ApolloServer',
@@ -39,7 +39,7 @@ module.exports = function (core) {
39
39
  const graphqlYoga = core.assess.configurationAnalysis.graphqlYoga = {};
40
40
 
41
41
  graphqlYoga.install = function () {
42
- return depHooks.resolve({ name: '@graphql-yoga/plugin-disable-introspection', version: '*', file: 'cjs' }, (xport) => patcher.patch(xport, 'useDisableIntrospection', {
42
+ return depHooks.resolve({ name: '@graphql-yoga/plugin-disable-introspection', version: '*' }, (xport) => patcher.patch(xport, 'useDisableIntrospection', {
43
43
  name: '@graphql-yoga/plugin-disable-introspection.useDisableIntrospection',
44
44
  patchType,
45
45
  post(data) {
@@ -34,7 +34,6 @@ module.exports = function(core) {
34
34
  require('./install/encode-uri')(core);
35
35
  require('./install/escape-html')(core);
36
36
  require('./install/escape')(core);
37
- require('./install/fastify-send')(core);
38
37
  require('./install/handlebars-utils-escape-expression')(core);
39
38
  require('./install/isnumeric-0')(core);
40
39
  require('./install/mustache-escape')(core);
@@ -48,7 +47,6 @@ module.exports = function(core) {
48
47
  require('./install/path')(core);
49
48
  require('./install/reg-exp-prototype-exec')(core);
50
49
  require('./install/joi')(core);
51
- require('./install/send')(core);
52
50
  require('./install/util-format')(core);
53
51
 
54
52
  propagation.install = function() {
@@ -41,6 +41,7 @@ module.exports = function(core) {
41
41
  tracker,
42
42
  sinks: { isVulnerable, reportFindings },
43
43
  },
44
+ ruleScopes
44
45
  },
45
46
  } = core;
46
47
 
@@ -60,12 +61,12 @@ module.exports = function(core) {
60
61
  }, []);
61
62
  }
62
63
 
63
- const pre = (name, method, moduleName = 'fs', fullMethodName = '') => (data) => {
64
+ const around = (name, method, moduleName = 'fs', fullMethodName = '') => (next, data) => {
64
65
  const { name: methodName, indices } = method;
65
- if (!getSinkContext(ruleId)) return;
66
+ if (!getSinkContext(ruleId)) return next();
66
67
 
67
68
  const values = getValues(indices, data.args);
68
- if (!values.length) return;
69
+ if (!values.length) return next();
69
70
 
70
71
  const args = values.map((v) => {
71
72
  const strInfo = tracker.getData(v);
@@ -111,6 +112,7 @@ module.exports = function(core) {
111
112
  });
112
113
  }
113
114
  }
115
+ return ruleScopes.run(ruleId, next);
114
116
  };
115
117
 
116
118
  core.assess.dataflow.sinks.pathTraversal = {
@@ -123,7 +125,7 @@ module.exports = function(core) {
123
125
  patcher.patch(fs, method.name, {
124
126
  name,
125
127
  patchType,
126
- pre: pre(name, method),
128
+ around: around(name, method),
127
129
  });
128
130
  }
129
131
 
@@ -134,19 +136,10 @@ module.exports = function(core) {
134
136
  patcher.patch(fs, syncName, {
135
137
  name,
136
138
  patchType,
137
- pre: pre(name, method, 'fs', syncName),
139
+ around: around(name, method, 'fs', syncName),
138
140
  });
139
141
  }
140
142
  }
141
-
142
- if (method.promises && fs.promises && fs.promises[method.name]) {
143
- const name = `fs.promises.${method.name}`;
144
- patcher.patch(fs.promises, method.name, {
145
- name,
146
- patchType,
147
- pre: pre(name, method, 'fs.promises'),
148
- });
149
- }
150
143
  }
151
144
  });
152
145
 
@@ -157,7 +150,7 @@ module.exports = function(core) {
157
150
  patcher.patch(fsPromises, method.name, {
158
151
  name,
159
152
  patchType,
160
- pre: pre(name, method, 'fsPromises'),
153
+ around: around(name, method, 'fsPromises'),
161
154
  });
162
155
  }
163
156
  }
@@ -17,9 +17,9 @@
17
17
 
18
18
  const {
19
19
  primordials: {
20
+ StringPrototypeSubstring,
20
21
  StringPrototypeToLowerCase,
21
22
  JSONStringify,
22
- StringPrototypeSubstring,
23
23
  },
24
24
  ResponseScanningRule,
25
25
  } = require('@contrast/common');
@@ -261,7 +261,7 @@ module.exports = function(core) {
261
261
  });
262
262
  };
263
263
 
264
- responseScanning.handleXPoweredByHeader = function(sourceContext, resHeaders) {
264
+ responseScanning.handleXPoweredByHeader = function (sourceContext, resHeaders) {
265
265
  if (!sourceContext.policy?.isRuleEnabled(X_POWERED_BY_HEADER)) return;
266
266
 
267
267
  const headerName = 'x-powered-by';
@@ -269,11 +269,13 @@ module.exports = function(core) {
269
269
 
270
270
  if (header) {
271
271
  header = StringPrototypeToLowerCase.call(header);
272
-
273
272
  reportFindings(sourceContext, {
274
273
  ruleId: ResponseScanningRule.X_POWERED_BY_HEADER,
275
274
  vulnerabilityMetadata: {
276
- platform: header,
275
+ snippet: header,
276
+ // the UI vuln title will read: X-Powered-By Header Enabled in Route
277
+ // ^^^^^
278
+ path: 'Route',
277
279
  }
278
280
  });
279
281
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/assess",
3
- "version": "1.65.0",
3
+ "version": "1.67.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)",
@@ -20,18 +20,18 @@
20
20
  "test": "bash ../scripts/test.sh"
21
21
  },
22
22
  "dependencies": {
23
- "@contrast/common": "1.38.0",
24
- "@contrast/config": "1.54.0",
25
- "@contrast/core": "1.59.0",
26
- "@contrast/dep-hooks": "1.28.0",
23
+ "@contrast/common": "1.39.0",
24
+ "@contrast/config": "1.55.0",
25
+ "@contrast/core": "1.60.0",
26
+ "@contrast/dep-hooks": "1.29.0",
27
27
  "@contrast/distringuish": "^6.0.2",
28
- "@contrast/instrumentation": "1.38.0",
29
- "@contrast/logger": "1.32.0",
30
- "@contrast/patcher": "1.31.0",
31
- "@contrast/rewriter": "1.36.0",
32
- "@contrast/route-coverage": "1.51.0",
33
- "@contrast/scopes": "1.29.0",
34
- "@contrast/sources": "1.5.0",
28
+ "@contrast/instrumentation": "1.39.0",
29
+ "@contrast/logger": "1.33.0",
30
+ "@contrast/patcher": "1.32.0",
31
+ "@contrast/rewriter": "1.37.0",
32
+ "@contrast/route-coverage": "1.53.0",
33
+ "@contrast/scopes": "1.30.0",
34
+ "@contrast/sources": "1.6.0",
35
35
  "semver": "^7.6.0"
36
36
  }
37
37
  }
@@ -1,60 +0,0 @@
1
- /*
2
- * Copyright: 2025 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 { primordials: { StringPrototypeSlice } } = require('@contrast/common');
18
- const { patchType } = require('../common');
19
-
20
- module.exports = function (core) {
21
- const {
22
- depHooks,
23
- patcher,
24
- } = core;
25
-
26
- return core.assess.dataflow.propagation.fastifySend = {
27
- install() {
28
- depHooks.resolve({ name: '@fastify/send', version: '<3', file: 'lib/SendStream.js' }, (SendStream) => {
29
- patcher.patch(SendStream.prototype, 'sendFile', {
30
- name: '@fastify/send/lib/SendStream.js',
31
- patchType,
32
- usePerf: 'sync',
33
- pre(data) {
34
- const { args } = data;
35
- // (†) This is a minimal propagator that just untracks the argument. There are
36
- // no propagation events generated and no expensive tag range computations. We
37
- // don't get the propagator context before proceeding since it could lead to false
38
- // positives e.g. if the number of propagation events exceeds the configured limit.
39
- const untrackedPath = StringPrototypeSlice.call(` ${args[0]}`, 1);
40
- args[0] = untrackedPath;
41
- },
42
- });
43
- });
44
-
45
- depHooks.resolve({ name: '@fastify/send', version: '>=3 <5', file: 'lib/send.js' }, (send) => {
46
- patcher.patch(send, 'send', {
47
- name: '@fastify/send/lib/send.js',
48
- patchType,
49
- usePerf: 'sync',
50
- pre(data) {
51
- const { args } = data;
52
- // (†)
53
- const untrackedPath = StringPrototypeSlice.call(` ${args[1]}`, 1);
54
- args[1] = untrackedPath;
55
- },
56
- });
57
- });
58
- }
59
- };
60
- };
@@ -1,57 +0,0 @@
1
- /*
2
- * Copyright: 2025 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 { patchType } = require('../common');
18
- const { primordials: { StringPrototypeSlice } } = require('@contrast/common');
19
-
20
- module.exports = function (core) {
21
- const {
22
- depHooks,
23
- patcher,
24
- } = core;
25
-
26
- const send = {};
27
- core.assess.dataflow.propagation.send = send;
28
-
29
- function patchSendModule(sendModuleExport) {
30
- return patcher.patch(sendModuleExport, {
31
- name: 'send',
32
- patchType,
33
- usePerf: 'sync',
34
- post(data) {
35
- patcher.patch(data.result, 'sendFile', {
36
- name: 'send.sendFile',
37
- patchType,
38
- pre(data) {
39
- const { args } = data;
40
- // This is a minimal propagator that just untracks the argument. There are
41
- // no propagation events generated and no expensive tag range computations. We
42
- // don't get the propagator context before proceeding since it could lead to false
43
- // positives e.g. if the number of propagation events exceeds the configured limit.
44
- const untrackedPath = StringPrototypeSlice.call(` ${args[0]}`, 1);
45
- args[0] = untrackedPath;
46
- },
47
- });
48
- },
49
- });
50
- }
51
-
52
- send.install = function () {
53
- depHooks.resolve({ name: 'send', version: '<2' }, patchSendModule);
54
- };
55
-
56
- return send;
57
- };