@contrast/assess 1.36.0 → 1.38.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.
Files changed (91) hide show
  1. package/lib/crypto-analysis/install/crypto.js +1 -1
  2. package/lib/dataflow/propagation/install/JSON/parse.js +1 -0
  3. package/lib/dataflow/propagation/install/JSON/stringify.js +1 -0
  4. package/lib/dataflow/propagation/install/array-prototype-join.js +1 -0
  5. package/lib/dataflow/propagation/install/buffer.js +1 -0
  6. package/lib/dataflow/propagation/install/contrast-methods/number.js +1 -0
  7. package/lib/dataflow/propagation/install/contrast-methods/string.js +1 -0
  8. package/lib/dataflow/propagation/install/contrast-methods/tag.js +1 -0
  9. package/lib/dataflow/propagation/install/decode-uri-component.js +1 -0
  10. package/lib/dataflow/propagation/install/ejs/escape-xml.js +1 -0
  11. package/lib/dataflow/propagation/install/ejs/template.js +1 -0
  12. package/lib/dataflow/propagation/install/encode-uri.js +1 -0
  13. package/lib/dataflow/propagation/install/escape-html.js +1 -0
  14. package/lib/dataflow/propagation/install/escape.js +1 -0
  15. package/lib/dataflow/propagation/install/fastify-send.js +1 -0
  16. package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +1 -0
  17. package/lib/dataflow/propagation/install/isnumeric-0.js +1 -0
  18. package/lib/dataflow/propagation/install/joi/boolean.js +2 -1
  19. package/lib/dataflow/propagation/install/joi/expression.js +2 -1
  20. package/lib/dataflow/propagation/install/joi/index.js +3 -1
  21. package/lib/dataflow/propagation/install/joi/keys.js +1 -0
  22. package/lib/dataflow/propagation/install/joi/number.js +2 -1
  23. package/lib/dataflow/propagation/install/joi/string-schema.js +3 -1
  24. package/lib/dataflow/propagation/install/joi/values.js +2 -1
  25. package/lib/dataflow/propagation/install/mongoose/schema-map.js +2 -0
  26. package/lib/dataflow/propagation/install/mongoose/schema-mixed.js +2 -0
  27. package/lib/dataflow/propagation/install/mongoose/schema-string.js +101 -1
  28. package/lib/dataflow/propagation/install/mongoose/schema-string.test.js +41 -2
  29. package/lib/dataflow/propagation/install/mustache-escape.js +1 -0
  30. package/lib/dataflow/propagation/install/mysql-connection-escape.js +3 -0
  31. package/lib/dataflow/propagation/install/parse-int.js +1 -0
  32. package/lib/dataflow/propagation/install/path/basename.js +1 -0
  33. package/lib/dataflow/propagation/install/path/dirname.js +1 -0
  34. package/lib/dataflow/propagation/install/path/extname.js +1 -0
  35. package/lib/dataflow/propagation/install/path/format.js +1 -0
  36. package/lib/dataflow/propagation/install/path/join-and-resolve.js +1 -0
  37. package/lib/dataflow/propagation/install/path/normalize.js +1 -0
  38. package/lib/dataflow/propagation/install/path/parse.js +2 -1
  39. package/lib/dataflow/propagation/install/path/relative.js +1 -0
  40. package/lib/dataflow/propagation/install/path/toNamespacedPath.js +1 -0
  41. package/lib/dataflow/propagation/install/pug/index.js +1 -0
  42. package/lib/dataflow/propagation/install/pug-runtime-escape.js +1 -0
  43. package/lib/dataflow/propagation/install/querystring/escape.js +2 -1
  44. package/lib/dataflow/propagation/install/querystring/parse.js +1 -0
  45. package/lib/dataflow/propagation/install/querystring/stringify.js +2 -1
  46. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +1 -0
  47. package/lib/dataflow/propagation/install/send.js +1 -0
  48. package/lib/dataflow/propagation/install/sequelize/query-generator.js +1 -0
  49. package/lib/dataflow/propagation/install/sequelize/sql-string.js +1 -0
  50. package/lib/dataflow/propagation/install/sql-template-strings.js +1 -0
  51. package/lib/dataflow/propagation/install/string/concat.js +1 -1
  52. package/lib/dataflow/propagation/install/string/format-methods.js +1 -1
  53. package/lib/dataflow/propagation/install/string/html-methods.js +1 -1
  54. package/lib/dataflow/propagation/install/string/index.js +1 -1
  55. package/lib/dataflow/propagation/install/string/match-all.js +1 -1
  56. package/lib/dataflow/propagation/install/string/match.js +1 -1
  57. package/lib/dataflow/propagation/install/string/replace.js +1 -1
  58. package/lib/dataflow/propagation/install/string/slice.js +1 -1
  59. package/lib/dataflow/propagation/install/string/split.js +1 -1
  60. package/lib/dataflow/propagation/install/string/substring.js +1 -1
  61. package/lib/dataflow/propagation/install/string/trim.js +3 -3
  62. package/lib/dataflow/propagation/install/unescape.js +1 -0
  63. package/lib/dataflow/propagation/install/url/domain-parsers.js +1 -0
  64. package/lib/dataflow/propagation/install/url/parse.js +2 -1
  65. package/lib/dataflow/propagation/install/url/searchParams.js +3 -1
  66. package/lib/dataflow/propagation/install/url/url.js +2 -1
  67. package/lib/dataflow/propagation/install/util-format.js +1 -0
  68. package/lib/dataflow/propagation/install/validator/hooks.js +2 -0
  69. package/lib/dataflow/sinks/install/child-process.js +1 -1
  70. package/lib/dataflow/sinks/install/express/unvalidated-redirect.js +1 -1
  71. package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js +1 -1
  72. package/lib/dataflow/sinks/install/fs-original.js +170 -0
  73. package/lib/dataflow/sinks/install/fs.js +1 -1
  74. package/lib/dataflow/sinks/install/function.js +1 -1
  75. package/lib/dataflow/sinks/install/hapi/unvalidated-redirect.js +1 -1
  76. package/lib/dataflow/sinks/install/http/request.js +1 -1
  77. package/lib/dataflow/sinks/install/koa/unvalidated-redirect.js +1 -1
  78. package/lib/dataflow/sinks/install/libxmljs.js +1 -1
  79. package/lib/dataflow/sinks/install/marsdb.js +1 -1
  80. package/lib/dataflow/sinks/install/mongodb.js +1 -1
  81. package/lib/dataflow/sinks/install/mysql.js +1 -1
  82. package/lib/dataflow/sinks/install/postgres.js +1 -1
  83. package/lib/dataflow/sinks/install/sequelize.js +1 -1
  84. package/lib/dataflow/sinks/install/vm.js +1 -1
  85. package/lib/sampler.js +1 -1
  86. package/lib/sampler.test.js +10 -5
  87. package/lib/session-configuration/install/express-session.js +1 -1
  88. package/lib/session-configuration/install/fastify-cookie.js +1 -1
  89. package/lib/session-configuration/install/hapi.js +1 -1
  90. package/lib/session-configuration/install/koa.js +1 -1
  91. package/package.json +9 -9
@@ -40,6 +40,7 @@ module.exports = function(core) {
40
40
  patcher.patch(path[os], 'relative', {
41
41
  name: `path.${os}.relative`,
42
42
  patchType,
43
+ usePerf: 'sync',
43
44
  post(data) {
44
45
  const { args, result, name, hooked, orig } = data;
45
46
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  patcher.patch(path[os], 'toNamespacedPath', {
40
40
  name: `path.${os}.toNamespacedPath`,
41
41
  patchType,
42
+ usePerf: 'sync',
42
43
  post(data) {
43
44
  const { args, result, name, hooked, orig } = data;
44
45
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -38,6 +38,7 @@ module.exports = function (core) {
38
38
  (pug) => patcher.patch(pug, 'compile', {
39
39
  name: 'pug.compile',
40
40
  patchType,
41
+ usePerf: 'tbd',
41
42
  pre(data) {
42
43
  if (!getSourceContext(PROPAGATOR)) return;
43
44
 
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  patcher.patch(pugRuntime, 'escape', {
40
40
  name,
41
41
  patchType,
42
+ usePerf: 'sync',
42
43
  post(data) {
43
44
  const { args, result, hooked, orig } = data;
44
45
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -23,7 +23,7 @@ module.exports = function(core) {
23
23
  const {
24
24
  assess: {
25
25
  getSourceContext,
26
- inspect, // todo: remove
26
+ inspect, // TODO NODE-3455: remove
27
27
  eventFactory: { createPropagationEvent },
28
28
  dataflow: { tracker }
29
29
  },
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(_export, 'escape', {
38
38
  name: 'querystring.escape',
39
39
  patchType,
40
+ usePerf: 'sync',
40
41
  post(data) {
41
42
  const [value] = data.args;
42
43
  if (!value?.length || !data.result?.length) return value;
@@ -105,6 +105,7 @@ module.exports = function(core) {
105
105
  patcher.patch(module, method, {
106
106
  name: `querystring.${method}`,
107
107
  patchType,
108
+ usePerf: 'sync',
108
109
  pre(data) {
109
110
  if (!data.args[0] || !getSourceContext(PROPAGATOR)) return;
110
111
 
@@ -26,7 +26,7 @@ module.exports = function(core) {
26
26
  const {
27
27
  assess: {
28
28
  getSourceContext,
29
- inspect, // todo: remove
29
+ inspect, // TODO NODE-3455: remove
30
30
  dataflow: { tracker },
31
31
  eventFactory: { createPropagationEvent },
32
32
  },
@@ -147,6 +147,7 @@ module.exports = function(core) {
147
147
  patcher.patch(_export, methodName, {
148
148
  name: `querystring.${methodName}`,
149
149
  patchType,
150
+ usePerf: 'sync',
150
151
  pre,
151
152
  post
152
153
  });
@@ -78,6 +78,7 @@ module.exports = function(core) {
78
78
  patcher.patch(RegExp.prototype, 'exec', {
79
79
  name,
80
80
  patchType,
81
+ usePerf: 'sync',
81
82
  post(data) {
82
83
  const { args, obj, result, hooked, orig } = data;
83
84
 
@@ -31,6 +31,7 @@ module.exports = function (core) {
31
31
  return patcher.patch(sendModuleExport, {
32
32
  name: 'send',
33
33
  patchType,
34
+ usePerf: 'sync',
34
35
  post(data) {
35
36
  patcher.patch(data.result, 'sendFile', {
36
37
  name: 'send.sendFile',
@@ -50,6 +50,7 @@ module.exports = function(core) {
50
50
  patcher.patch(_export.prototype, 'quoteIdentifier', {
51
51
  name: `sequelize.${constructor}.prototype.quoteIdentifier`,
52
52
  patchType,
53
+ usePerf: 'sync',
53
54
  post(data) {
54
55
  const strInfo = tracker.getData(data.result);
55
56
  if (!strInfo || !getSourceContext()) return;
@@ -62,6 +62,7 @@ module.exports = function(core) {
62
62
  patcher.patch(sqlString, 'escape', {
63
63
  name,
64
64
  patchType,
65
+ usePerf: 'sync',
65
66
  post(data) {
66
67
  const { args, result, hooked, orig } = data;
67
68
 
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(sqlTemplateStrings, 'SQL', {
38
38
  name,
39
39
  patchType,
40
+ usePerf: 'sync',
40
41
  post(data) {
41
42
  const { args, result, hooked, orig } = data;
42
43
  if (!result || !args[0] || !getSourceContext()) return;
@@ -37,7 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(String.prototype, 'concat', {
38
38
  name,
39
39
  patchType,
40
- usePerf: true,
40
+ usePerf: 'sync',
41
41
  post(data) {
42
42
  const { obj, result, hooked, orig } = data;
43
43
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -36,7 +36,7 @@ module.exports = function(core) {
36
36
  patcher.patch(String.prototype, method, {
37
37
  name,
38
38
  patchType,
39
- usePerf: true,
39
+ usePerf: 'sync',
40
40
  post(data) {
41
41
  const { obj, result, hooked, orig } = data;
42
42
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -32,7 +32,7 @@ module.exports = function(core) {
32
32
  const {
33
33
  patcher,
34
34
  assess: {
35
- inspect, // todo: remove
35
+ inspect, // TODO NODE-3455: remove
36
36
  getSourceContext,
37
37
  eventFactory: { createPropagationEvent },
38
38
  dataflow: { tracker }
@@ -45,7 +45,7 @@ module.exports = function(core) {
45
45
  return patcher.patch(matcherFn, {
46
46
  name,
47
47
  patchType,
48
- usePerf: true,
48
+ usePerf: 'sync',
49
49
  pre(data) {
50
50
  const { args: origArgs, hooked, orig } = data;
51
51
  if (
@@ -75,7 +75,7 @@ module.exports = function(core) {
75
75
  patcher.patch(String.prototype, 'matchAll', {
76
76
  name,
77
77
  patchType,
78
- usePerf: true,
78
+ usePerf: 'sync',
79
79
  around(origFn, data) {
80
80
  const { args, obj, hooked, orig } = data;
81
81
 
@@ -79,7 +79,7 @@ module.exports = function(core) {
79
79
  patcher.patch(String.prototype, 'match', {
80
80
  name,
81
81
  patchType,
82
- usePerf: true,
82
+ usePerf: 'sync',
83
83
  around(origFn, data) {
84
84
  const { args, obj } = data;
85
85
  if (
@@ -150,7 +150,7 @@ module.exports = function(core) {
150
150
  patcher.patch(String.prototype, 'replace', {
151
151
  name,
152
152
  patchType,
153
- usePerf: true,
153
+ usePerf: 'sync',
154
154
  pre(data) {
155
155
  if (!getSourceContext(PROPAGATOR)) return;
156
156
 
@@ -54,7 +54,7 @@ module.exports = function(core) {
54
54
  patcher.patch(String.prototype, 'slice', {
55
55
  name,
56
56
  patchType,
57
- usePerf: true,
57
+ usePerf: 'sync',
58
58
  post(data) {
59
59
  const { name, args: origArgs, obj, result, hooked, orig } = data;
60
60
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -37,7 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(String.prototype, 'split', {
38
38
  name,
39
39
  patchType,
40
- usePerf: true,
40
+ usePerf: 'sync',
41
41
  post(data) {
42
42
  const { name, args: origArgs, obj, result, hooked, orig } = data;
43
43
  if (
@@ -62,7 +62,7 @@ module.exports = function(core) {
62
62
  patcher.patch(String.prototype, method, {
63
63
  name: `String.prototype.${method}`,
64
64
  patchType,
65
- usePerf: true,
65
+ usePerf: 'sync',
66
66
  post(data) {
67
67
  const { obj, args: origArgs, result, name, hooked, orig } = data;
68
68
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -92,21 +92,21 @@ module.exports = function(core) {
92
92
  name: 'String.prototype.trim',
93
93
  patchType,
94
94
  post: createPostHook('trim'),
95
- usePerf: true,
95
+ usePerf: 'sync',
96
96
  });
97
97
 
98
98
  patcher.patch(String.prototype, 'trimStart', {
99
99
  name: 'String.prototype.trimStart',
100
100
  patchType,
101
101
  post: createPostHook('trimStart'),
102
- usePerf: true,
102
+ usePerf: 'sync',
103
103
  });
104
104
 
105
105
  patcher.patch(String.prototype, 'trimEnd', {
106
106
  name: 'String.prototype.trimEnd',
107
107
  patchType,
108
108
  post: createPostHook('trimEnd', 0),
109
- usePerf: true,
109
+ usePerf: 'sync',
110
110
  });
111
111
  },
112
112
  uninstall() {
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(global, 'unescape', {
38
38
  name,
39
39
  patchType,
40
+ usePerf: 'sync',
40
41
  post(data) {
41
42
  const { args, result, hooked, orig } = data;
42
43
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  patcher.patch(url, method, {
40
40
  name,
41
41
  patchType,
42
+ usePerf: 'sync',
42
43
  post(data) {
43
44
  const { args, result, hooked, orig } = data;
44
45
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -24,7 +24,7 @@ module.exports = function(core) {
24
24
  depHooks,
25
25
  assess: {
26
26
  getSourceContext,
27
- inspect, // todo: remove
27
+ inspect, // TODO NODE-3455: remove
28
28
  eventFactory: { createPropagationEvent },
29
29
  dataflow: { tracker }
30
30
  }
@@ -87,6 +87,7 @@ module.exports = function(core) {
87
87
  patcher.patch(url, 'parse', {
88
88
  name,
89
89
  patchType,
90
+ usePerf: 'sync',
90
91
  post(data) {
91
92
  const { args, result, hooked, orig } = data;
92
93
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -25,7 +25,7 @@ module.exports = function(core) {
25
25
  patcher,
26
26
  depHooks,
27
27
  assess: {
28
- inspect, // todo: remove
28
+ inspect, // TODO NODE-3455: remove
29
29
  getSourceContext,
30
30
  eventFactory: { createPropagationEvent },
31
31
  dataflow: { tracker }
@@ -66,6 +66,7 @@ module.exports = function(core) {
66
66
  patcher.patch(url, 'URLSearchParams', {
67
67
  name,
68
68
  patchType,
69
+ usePerf: 'sync',
69
70
  post(data) {
70
71
  const { args, obj, result } = data;
71
72
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -120,6 +121,7 @@ module.exports = function(core) {
120
121
  patcher.patch(obj.prototype, 'toString', {
121
122
  name: 'url.URLSearchParams.toString',
122
123
  patchType,
124
+ usePerf: 'sync',
123
125
  post(data) {
124
126
  const { obj: params } = data;
125
127
 
@@ -26,7 +26,7 @@ module.exports = function(core) {
26
26
  depHooks,
27
27
  assess: {
28
28
  getSourceContext,
29
- inspect, // todo: remove
29
+ inspect, // TODO NODE-3455: remove
30
30
  eventFactory: { createPropagationEvent },
31
31
  dataflow: { tracker }
32
32
  }
@@ -92,6 +92,7 @@ module.exports = function(core) {
92
92
  patcher.patch(url, 'URL', {
93
93
  name,
94
94
  patchType,
95
+ usePerf: 'sync',
95
96
  post(data) {
96
97
  const { args, result } = data;
97
98
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  return patcher.patch(util, 'format', {
40
40
  name,
41
41
  patchType,
42
+ usePerf: 'sync',
42
43
  post(data) {
43
44
  const { args, result, hooked, orig } = data;
44
45
  if (!result || !args[0] || !isString(args[0]) || !getSourceContext(PROPAGATOR)) return;
@@ -70,6 +70,7 @@ module.exports = function (core) {
70
70
  return patcher.patch(...getPatcherArgs(index), {
71
71
  name,
72
72
  patchType,
73
+ usePerf: 'sync',
73
74
  post(data) {
74
75
  const matches = validator === 'matches';
75
76
  if (
@@ -105,6 +106,7 @@ module.exports = function (core) {
105
106
  (index) => patcher.patch(...getPatcherArgs(index), {
106
107
  name: `validator.${untracker}`,
107
108
  patchType,
109
+ usePerf: 'sync',
108
110
  post(data) {
109
111
  if (data.result && getSourceContext()) {
110
112
  const trackingData = tracker.getData(data.args[0]);
@@ -34,7 +34,7 @@ module.exports = function(core) {
34
34
  depHooks,
35
35
  patcher,
36
36
  assess: {
37
- inspect, // todo: remove
37
+ inspect, // TODO NODE-3455: remove
38
38
  getSourceContext,
39
39
  eventFactory: { createSinkEvent },
40
40
  dataflow: {
@@ -45,7 +45,7 @@ module.exports = function(core) {
45
45
  patcher,
46
46
  config,
47
47
  assess: {
48
- inspect, // todo: remove
48
+ inspect, // TODO NODE-3455: remove
49
49
  getSourceContext,
50
50
  eventFactory: { createSinkEvent },
51
51
  dataflow: {
@@ -64,7 +64,7 @@ module.exports = function(core) {
64
64
  depHooks,
65
65
  patcher,
66
66
  assess: {
67
- inspect, // todo: remove
67
+ inspect, // TODO NODE-3455: remove
68
68
  getSourceContext,
69
69
  eventFactory: { createSinkEvent },
70
70
  dataflow: {
@@ -0,0 +1,170 @@
1
+ /*
2
+ * Copyright: 2024 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
+ const { patchType } = require('../common');
17
+
18
+ const {
19
+ DataflowTag: {
20
+ URL_ENCODED,
21
+ LIMITED_CHARS,
22
+ ALPHANUM_SPACE_HYPHEN,
23
+ SAFE_PATH,
24
+ UNTRUSTED,
25
+ },
26
+ FS_METHODS,
27
+ Rule: { PATH_TRAVERSAL: ruleId },
28
+ isString,
29
+ ArrayPrototypeJoin,
30
+ } = require('@contrast/common');
31
+ const { InstrumentationType: { RULE } } = require('../../../constants');
32
+
33
+ module.exports = function(core) {
34
+ const {
35
+ depHooks,
36
+ patcher,
37
+ assess: {
38
+ inspect, // TODO NODE-3455: remove
39
+ getSourceContext,
40
+ eventFactory: { createSinkEvent },
41
+ dataflow: {
42
+ tracker,
43
+ sinks: { isVulnerable, reportFindings },
44
+ },
45
+ },
46
+ } = core;
47
+
48
+ const safeTags = [
49
+ `excluded:${ruleId}`,
50
+ URL_ENCODED,
51
+ LIMITED_CHARS,
52
+ ALPHANUM_SPACE_HYPHEN,
53
+ SAFE_PATH,
54
+ ];
55
+
56
+ function getValues(indices, args) {
57
+ return indices.reduce((acc, idx) => {
58
+ const value = args[idx];
59
+ if (value && isString(value)) acc.push(value);
60
+ return acc;
61
+ }, []);
62
+ }
63
+
64
+ const pre = (name, method, moduleName = 'fs', fullMethodName = '') => (data) => {
65
+ const { name: methodName, indices } = method;
66
+ if (!getSourceContext(RULE, ruleId)) return;
67
+
68
+ const values = getValues(indices, data.args);
69
+ if (!values.length) return;
70
+
71
+ const args = values.map((v) => {
72
+ const strInfo = tracker.getData(v);
73
+ return {
74
+ value: strInfo ? strInfo.value : v,
75
+ tracked: !!strInfo,
76
+ strInfo
77
+ };
78
+ });
79
+ for (let i = 0; i < values.length; i++) {
80
+ const { strInfo } = args[i];
81
+
82
+ if (!strInfo || !isVulnerable(UNTRUSTED, safeTags, strInfo.tags)) {
83
+ continue;
84
+ }
85
+
86
+ const event = createSinkEvent({
87
+ name,
88
+ moduleName,
89
+ methodName: fullMethodName || methodName,
90
+ context: `${name}(${ArrayPrototypeJoin.call(
91
+ args.map((a) => inspect(a.value)),
92
+ ', '
93
+ )})`,
94
+ history: [strInfo],
95
+ object: {
96
+ value: 'fs',
97
+ tracked: false,
98
+ },
99
+ args: args.map(({ value, tracked }) => ({ value, tracked })),
100
+ tags: strInfo.tags,
101
+ source: `P${i}`,
102
+ stacktraceOpts: {
103
+ contructorOpt: data.hooked,
104
+ prependFrames: [data.orig],
105
+ },
106
+ });
107
+
108
+ if (event) {
109
+ reportFindings({
110
+ ruleId,
111
+ sinkEvent: event,
112
+ });
113
+ }
114
+ }
115
+ };
116
+
117
+ core.assess.dataflow.sinks.pathTraversal = {
118
+ install() {
119
+ depHooks.resolve({ name: 'fs' }, (fs) => {
120
+ for (const method of FS_METHODS) {
121
+ // not all methods are available on every OS or Node version.
122
+ if (fs[method.name]) {
123
+ const name = `fs.${method.name}`;
124
+ patcher.patch(fs, method.name, {
125
+ name,
126
+ patchType,
127
+ pre: pre(name, method),
128
+ });
129
+ }
130
+
131
+ if (method.sync) {
132
+ const syncName = `${method.name}Sync`;
133
+ if (fs[syncName]) {
134
+ const name = `fs.${syncName}`;
135
+ patcher.patch(fs, syncName, {
136
+ name,
137
+ patchType,
138
+ pre: pre(name, method, 'fs', syncName),
139
+ });
140
+ }
141
+ }
142
+
143
+ if (method.promises && fs.promises && fs.promises[method.name]) {
144
+ const name = `fs.promises.${method.name}`;
145
+ patcher.patch(fs.promises, method.name, {
146
+ name,
147
+ patchType,
148
+ pre: pre(name, method, 'fs.promises'),
149
+ });
150
+ }
151
+ }
152
+ });
153
+
154
+ depHooks.resolve({ name: 'fs/promises' }, (fsPromises) => {
155
+ for (const method of FS_METHODS) {
156
+ if (method.promises && fsPromises[method.name]) {
157
+ const name = `fsPromises.${method.name}`;
158
+ patcher.patch(fsPromises, method.name, {
159
+ name,
160
+ patchType,
161
+ pre: pre(name, method, 'fsPromises'),
162
+ });
163
+ }
164
+ }
165
+ });
166
+ },
167
+ };
168
+
169
+ return core.assess.dataflow.sinks.pathTraversal;
170
+ };
@@ -35,7 +35,7 @@ module.exports = function(core) {
35
35
  depHooks,
36
36
  patcher,
37
37
  assess: {
38
- inspect, // todo: remove
38
+ inspect, // TODO NODE-3455: remove
39
39
  getSourceContext,
40
40
  eventFactory: { createSinkEvent },
41
41
  dataflow: {
@@ -46,7 +46,7 @@ module.exports = function (core) {
46
46
  logger,
47
47
  patcher,
48
48
  assess: {
49
- inspect, // todo: remove
49
+ inspect, // TODO NODE-3455: remove
50
50
  getSourceContext,
51
51
  eventFactory: { createSinkEvent },
52
52
  dataflow: {
@@ -45,7 +45,7 @@ module.exports = function(core) {
45
45
  patcher,
46
46
  config,
47
47
  assess: {
48
- inspect, // todo: remove
48
+ inspect, // TODO NODE-3455: remove
49
49
  getSourceContext,
50
50
  eventFactory: { createSinkEvent },
51
51
  dataflow: {
@@ -46,7 +46,7 @@ module.exports = function(core) {
46
46
  depHooks,
47
47
  patcher,
48
48
  assess: {
49
- inspect, // todo: remove
49
+ inspect, // TODO NODE-3455: remove
50
50
  getSourceContext,
51
51
  eventFactory: { createSinkEvent },
52
52
  dataflow: {
@@ -46,7 +46,7 @@ module.exports = function(core) {
46
46
  patcher,
47
47
  config,
48
48
  assess: {
49
- inspect, // todo: remove
49
+ inspect, // TODO NODE-3455: remove
50
50
  getSourceContext,
51
51
  eventFactory: { createSinkEvent },
52
52
  dataflow: {
@@ -47,7 +47,7 @@ module.exports = function(core) {
47
47
  depHooks,
48
48
  patcher,
49
49
  assess: {
50
- inspect, // todo: remove
50
+ inspect, // TODO NODE-3455: remove
51
51
  getSourceContext,
52
52
  eventFactory: { createSinkEvent },
53
53
  dataflow: {
@@ -50,7 +50,7 @@ module.exports = function (core) {
50
50
  logger,
51
51
  patcher,
52
52
  assess: {
53
- inspect, // todo: remove
53
+ inspect, // TODO NODE-3455: remove
54
54
  getSourceContext,
55
55
  eventFactory: { createSinkEvent },
56
56
  dataflow: {
@@ -82,7 +82,7 @@ module.exports = function (core) {
82
82
  logger,
83
83
  patcher,
84
84
  assess: {
85
- inspect, // todo: remove
85
+ inspect, // TODO NODE-3455: remove
86
86
  getSourceContext,
87
87
  eventFactory: { createSinkEvent },
88
88
  dataflow: {
@@ -53,7 +53,7 @@ module.exports = function(core) {
53
53
  depHooks,
54
54
  patcher,
55
55
  assess: {
56
- inspect, // todo: remove
56
+ inspect, // TODO NODE-3455: remove
57
57
  getSourceContext,
58
58
  eventFactory: { createSinkEvent },
59
59
  dataflow: {