@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
@@ -50,7 +50,7 @@ const SAFE_HASH_ALGORITHMS = new Set([
50
50
  'sha512',
51
51
  'sha512withrsaencryption',
52
52
  ]);
53
- const SAFE_HASH_LIBS = ['etag', 'browserify', 'deps-sort'];
53
+ const SAFE_HASH_LIBS = ['etag', 'browserify', 'deps-sort', 'cookie-signature'];
54
54
  const SAFE_CIPHER_ALGORITHM_PREFIXES = ['des-ede', 'id-aes', 'aes', 'rsa'];
55
55
 
56
56
  /**
@@ -100,6 +100,7 @@ module.exports = function (core) {
100
100
  patcher.patch(JSON, 'parse', {
101
101
  name: 'JSON.parse',
102
102
  patchType,
103
+ usePerf: 'sync',
103
104
  pre(data) {
104
105
  if (!data.args[0] || !getSourceContext(PROPAGATOR)) return;
105
106
  const [input, reviver] = data.args;
@@ -165,6 +165,7 @@ module.exports = function(core) {
165
165
  patcher.patch(JSON, 'stringify', {
166
166
  name: 'JSON.stringify',
167
167
  patchType,
168
+ usePerf: 'sync',
168
169
  pre(data) {
169
170
  if (!getSourceContext(PROPAGATOR)) return;
170
171
 
@@ -69,6 +69,7 @@ module.exports = function(core) {
69
69
  patcher.patch(Array.prototype, 'join', {
70
70
  name,
71
71
  patchType,
72
+ usePerf: 'sync',
72
73
  post(data) {
73
74
  const { args: origArgs, obj, result, hooked, orig } = data;
74
75
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -82,6 +82,7 @@ module.exports = function(core) {
82
82
  patcher.patch(global.Buffer, 'from', {
83
83
  patchType,
84
84
  name: bufferFrom,
85
+ usePerf: 'sync',
85
86
  post(data) {
86
87
  const firstArg = data.args[0];
87
88
  const argType = isString(firstArg) ? 'string' : Buffer.isBuffer(firstArg) ? 'buffer' : null;
@@ -36,6 +36,7 @@ module.exports = function (core) {
36
36
  patcher.patch(global.ContrastMethods, 'Number', {
37
37
  name,
38
38
  patchType,
39
+ usePerf: 'sync',
39
40
  post(data) {
40
41
  const { args: [value], result } = data;
41
42
  if (
@@ -44,6 +44,7 @@ module.exports = function(core) {
44
44
  patcher.patch(global.ContrastMethods, 'String', {
45
45
  name,
46
46
  patchType,
47
+ usePerf: 'sync',
47
48
  post(data) {
48
49
  if (!data.result || !getSourceContext(PROPAGATOR)) return;
49
50
 
@@ -33,6 +33,7 @@ module.exports = function(core) {
33
33
  patcher.patch(global.ContrastMethods, 'tag', {
34
34
  name: 'ContrastMethods.tag',
35
35
  patchType,
36
+ usePerf: 'sync',
36
37
  post(data) {
37
38
  if (!data.result || !getSourceContext(PROPAGATOR)) {
38
39
  return;
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(global, 'decodeURIComponent', {
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;
@@ -38,6 +38,7 @@ module.exports = function(core) {
38
38
  patcher.patch(ejsUtils, 'escapeXML', {
39
39
  name,
40
40
  patchType,
41
+ usePerf: 'sync',
41
42
  post(data) {
42
43
  const { args, result, hooked, orig } = data;
43
44
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -60,6 +60,7 @@ module.exports = function (core) {
60
60
  patcher.patch(_export.Template.prototype, 'generateSource', {
61
61
  name: 'ejs.Template.prototype.generateSource',
62
62
  patchType,
63
+ usePerf: 'sync',
63
64
  post(data) {
64
65
  if (!getSourceContext(PROPAGATOR)) return;
65
66
 
@@ -48,6 +48,7 @@ module.exports = function(core) {
48
48
  patcher.patch(global, methodName, {
49
49
  name,
50
50
  patchType,
51
+ usePerf: 'sync',
51
52
  post(data) {
52
53
  const { args, result, hooked, orig } = data;
53
54
  if (!result || !args[0] || !getSourceContext(PROPAGATOR)) return;
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  return patcher.patch(escapeHtml, {
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;
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(global, 'escape', {
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;
@@ -30,6 +30,7 @@ module.exports = function (core) {
30
30
  patcher.patch(_SendStream.prototype, 'sendFile', {
31
31
  name: '@fastify/send/lib/SendStream.js',
32
32
  patchType,
33
+ usePerf: 'sync',
33
34
  pre(data) {
34
35
  const { args } = data;
35
36
 
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  patcher.patch(handlebars.Utils, 'escapeExpression', {
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;
@@ -38,6 +38,7 @@ module.exports = function (core) {
38
38
  return patcher.patch(_export, {
39
39
  name,
40
40
  patchType,
41
+ usePerf: 'sync',
41
42
  post(data) {
42
43
  const { args: [value], result } = data;
43
44
  if (
@@ -26,7 +26,7 @@ module.exports = function(core) {
26
26
  patcher,
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
  },
@@ -45,6 +45,7 @@ module.exports = function(core) {
45
45
  patcher.patch(def.coerce, 'method', {
46
46
  name: 'joi.boolean.coerce',
47
47
  patchType,
48
+ usePerf: 'sync',
48
49
  post(data) {
49
50
  if (
50
51
  !data.result?.value ||
@@ -24,7 +24,7 @@ module.exports = function(core) {
24
24
  patcher,
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
  },
@@ -38,6 +38,7 @@ module.exports = function(core) {
38
38
  return patcher.patch(joi, method, {
39
39
  name: `joi.${method}`,
40
40
  patchType,
41
+ usePerf: 'sync',
41
42
  post(data) {
42
43
  if (!data.result || !getSourceContext()) return;
43
44
 
@@ -29,7 +29,7 @@ module.exports = function(core) {
29
29
  patcher,
30
30
  assess: {
31
31
  getSourceContext,
32
- inspect, // todo: remove
32
+ inspect, // TODO NODE-3455: remove
33
33
  eventFactory: { createPropagationEvent },
34
34
  dataflow: { tracker },
35
35
  },
@@ -46,6 +46,7 @@ module.exports = function(core) {
46
46
  patcher.patch(parentObj, 'validateAsync', {
47
47
  name: `Joi.${parentObjType}.validateAsync`,
48
48
  patchType,
49
+ usePerf: 'tbd',
49
50
  post(data) {
50
51
  const childNodes = data.obj?.$_terms.items?.length
51
52
  ? data.obj.$_terms.items
@@ -96,6 +97,7 @@ module.exports = function(core) {
96
97
  patcher.patch(parentObj.rules.custom, 'validate', {
97
98
  name: `joi.${objName}.custom.valdiate`,
98
99
  patchType,
100
+ usePerf: 'sync',
99
101
  post(data) {
100
102
  const {
101
103
  args: [input, schema],
@@ -131,6 +131,7 @@ module.exports = function(core) {
131
131
  patcher.patch(Object.getPrototypeOf(joi), 'keys', {
132
132
  name: 'joi.keys',
133
133
  patchType,
134
+ usePerf: 'sync',
134
135
  pre(data) {
135
136
  const [value] = data.args;
136
137
  const joi = data.obj.$_root;
@@ -26,7 +26,7 @@ module.exports = function(core) {
26
26
  patcher,
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
  },
@@ -43,6 +43,7 @@ module.exports = function(core) {
43
43
  patcher.patch(def.coerce, 'method', {
44
44
  name: 'joi.number.coerce',
45
45
  patchType,
46
+ usePerf: 'sync',
46
47
  post(data) {
47
48
  if (
48
49
  !data.result?.value ||
@@ -42,7 +42,7 @@ module.exports = function(core) {
42
42
  patcher,
43
43
  assess: {
44
44
  getSourceContext,
45
- inspect, // todo: remove
45
+ inspect, // TODO NODE-3455: remove
46
46
  eventFactory: { createPropagationEvent },
47
47
  dataflow: {
48
48
  tracker, propagation: {
@@ -105,6 +105,7 @@ module.exports = function(core) {
105
105
  patcher.patch(validatorObj, 'validate', {
106
106
  name: patchName,
107
107
  patchType,
108
+ usePerf: 'sync',
108
109
  post(data) {
109
110
  const [input, schema] = data.args;
110
111
 
@@ -137,6 +138,7 @@ module.exports = function(core) {
137
138
  patcher.patch(coerce, 'method', {
138
139
  name: 'joi.string._definition.coerce',
139
140
  patchType,
141
+ usePerf: 'sync',
140
142
  post(data) {
141
143
  const { args, result } = data;
142
144
 
@@ -27,7 +27,7 @@ module.exports = function(core) {
27
27
  patcher,
28
28
  assess: {
29
29
  getSourceContext,
30
- inspect, // todo: remove
30
+ inspect, // TODO NODE-3455: remove
31
31
  eventFactory: { createPropagationEvent },
32
32
  dataflow: { tracker },
33
33
  },
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(values.prototype, 'get', {
38
38
  name: 'joi.values',
39
39
  patchType,
40
+ usePerf: 'sync',
40
41
  post(data) {
41
42
  const {
42
43
  args: [value, state, prefs],
@@ -107,6 +107,7 @@ module.exports = function (core) {
107
107
  patcher.patch(SchemaMap.prototype, 'doValidateSync', {
108
108
  name: doValidateSyncName,
109
109
  patchType,
110
+ usePerf: 'sync',
110
111
  post: (data) => {
111
112
  if (!assess.trust_custom_validators || data.result || !getSourceContext()) return;
112
113
 
@@ -119,6 +120,7 @@ module.exports = function (core) {
119
120
  patcher.patch(SchemaMap.prototype, 'doValidate', {
120
121
  name: doValidateName,
121
122
  patchType,
123
+ usePerf: 'tbd',
122
124
  pre: (data) => {
123
125
  if (!assess.trust_custom_validators) return;
124
126
 
@@ -134,6 +134,7 @@ module.exports = function (core) {
134
134
  patcher.patch(SchemaMixed.prototype, 'doValidate', {
135
135
  name: doValidateName,
136
136
  patchType,
137
+ usePerf: 'tbd',
137
138
  pre: (data) => {
138
139
  if (!assess.trust_custom_validators || !getSourceContext()) {
139
140
  return;
@@ -147,6 +148,7 @@ module.exports = function (core) {
147
148
  data.args[1] = patcher.patch(cb, {
148
149
  name: doValidateName,
149
150
  patchType,
151
+ usePerf: 'tbd',
150
152
  pre({ args: [err] }) {
151
153
  if (err) return;
152
154
 
@@ -15,6 +15,7 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const semver = require('semver');
18
19
  const { DataflowTag, primordials: { StringPrototypeSubstring } } = require('@contrast/common');
19
20
  const { patchType } = require('../../common');
20
21
  const { userDefinedType } = require('./common');
@@ -34,10 +35,104 @@ module.exports = function (core) {
34
35
  },
35
36
  } = core;
36
37
 
38
+ function patchCastForQuery(SchemaString, { version }) {
39
+ if (semver.gte(version, '7.0.0')) {
40
+ patcher.patch(SchemaString.prototype, 'castForQuery', {
41
+ name: 'mongoose.SchemaString.prototype.castForQuery',
42
+ patchType,
43
+ post(data) {
44
+ // if a conditional is provided as the first argument castForQuery gets
45
+ // called subsequently with the individual value(s)
46
+ if (!getSourceContext() || data.args[0]) return;
47
+
48
+ const strInfo = tracker.getData(data.result);
49
+ if (!strInfo) return;
50
+
51
+ const event = createPropagationEvent({
52
+ addedTags: [DataflowTag.STRING_TYPE_CHECKED],
53
+ name: data.name,
54
+ moduleName: 'mongoose',
55
+ methodName: 'SchemaString.prototype.castForQuery',
56
+ history: [{ ...strInfo }],
57
+ object: {
58
+ tracked: false,
59
+ value: 'mongoose.SchemaString',
60
+ },
61
+ args: [{ tracked: true, value: strInfo.value }],
62
+ result: { tracked: true, value: data.result },
63
+ source: 'P1',
64
+ tags: {
65
+ ...strInfo.tags,
66
+ [DataflowTag.STRING_TYPE_CHECKED]: [0, data.result.length - 1],
67
+ },
68
+ target: 'R',
69
+ stacktraceOpts: {
70
+ prependFrames: [data.orig],
71
+ },
72
+ });
73
+
74
+ if (!event) return;
75
+
76
+ // in case the event type changed e.g. Source->Propagation
77
+ for (const key of Object.keys(strInfo)) {
78
+ if (key === 'value' || key === 'extern') continue;
79
+ delete strInfo[key];
80
+ }
81
+
82
+ Object.assign(strInfo, event);
83
+ }
84
+ });
85
+ } else {
86
+ // v6
87
+ patcher.patch(SchemaString.prototype, '_castForQuery', {
88
+ name: 'mongoose.SchemaString.prototype._castForQuery',
89
+ patchType,
90
+ post(data) {
91
+ const strInfo = tracker.getData(data.result);
92
+ if (!strInfo) return;
93
+
94
+ const event = createPropagationEvent({
95
+ addedTags: [DataflowTag.STRING_TYPE_CHECKED],
96
+ name: data.name,
97
+ moduleName: 'mongoose',
98
+ methodName: 'SchemaString.prototype._castForQuery',
99
+ history: [{ ...strInfo }],
100
+ object: {
101
+ tracked: false,
102
+ value: 'mongoose.SchemaString',
103
+ },
104
+ args: [{ tracked: true, value: strInfo.value }],
105
+ result: { tracked: true, value: data.result },
106
+ source: 'P0',
107
+ tags: {
108
+ ...strInfo.tags,
109
+ [DataflowTag.STRING_TYPE_CHECKED]: [0, data.result.length - 1],
110
+ },
111
+ target: 'R',
112
+ stacktraceOpts: {
113
+ prependFrames: [data.orig],
114
+ },
115
+ });
116
+
117
+ if (!event) return;
118
+
119
+ // in case the event type changed e.g. Source->Propagation
120
+ for (const key of Object.keys(strInfo)) {
121
+ if (key === 'value' || key === 'extern') continue;
122
+ delete strInfo[key];
123
+ }
124
+
125
+ Object.assign(strInfo, event);
126
+ }
127
+ });
128
+ }
129
+ }
130
+
37
131
  function patchEnum(SchemaString) {
38
132
  patcher.patch(SchemaString.prototype, 'enum', {
39
133
  name: 'mongoose.SchemaString.prototype.enum',
40
134
  patchType,
135
+ usePerf: 'sync',
41
136
  post(data) {
42
137
  if (!data.result) return;
43
138
 
@@ -50,6 +145,7 @@ module.exports = function (core) {
50
145
  patcher.patch(enumValidator, 'validator', {
51
146
  name: 'mongoose.SchemaString.prototype.enum.validator',
52
147
  patchType,
148
+ usePerf: 'sync',
53
149
  post(data) {
54
150
  const sourceContext = sources.getStore()?.assess;
55
151
  if (!sourceContext) return;
@@ -69,6 +165,7 @@ module.exports = function (core) {
69
165
  patcher.patch(SchemaString.prototype, 'doValidate', {
70
166
  name,
71
167
  patchType,
168
+ usePerf: 'tbd',
72
169
  pre(data) {
73
170
  const [value, cb] = data.args;
74
171
  if (!value || typeof cb !== 'function' || !getSourceContext()) return;
@@ -80,6 +177,7 @@ module.exports = function (core) {
80
177
  data.args[1] = patcher.patch(cb, {
81
178
  name,
82
179
  patchType,
180
+ usePerf: 'tbd',
83
181
  pre(data) {
84
182
  const {
85
183
  args: [err],
@@ -109,6 +207,7 @@ module.exports = function (core) {
109
207
  patcher.patch(SchemaString.prototype, 'doValidateSync', {
110
208
  name,
111
209
  patchType,
210
+ usePerf: 'sync',
112
211
  post(data) {
113
212
  const {
114
213
  args: [value],
@@ -196,7 +295,8 @@ module.exports = function (core) {
196
295
  file: 'lib/schema/string.js',
197
296
  version: '>=6.0.0',
198
297
  },
199
- (SchemaString) => {
298
+ (SchemaString, metadata) => {
299
+ patchCastForQuery(SchemaString, metadata);
200
300
  patchEnum(SchemaString);
201
301
  patchDoValidate(SchemaString);
202
302
  patchDoValidateSync(SchemaString);
@@ -4,7 +4,7 @@ const { expect } = require('chai');
4
4
  const sinon = require('sinon');
5
5
  const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
- describe('assess dataflow propagation mongoose.StringSchema', function () {
7
+ describe('assess dataflow propagation mongoose.SchemaString', function () {
8
8
  let core,
9
9
  trackString,
10
10
  simulateRequestScope,
@@ -28,6 +28,9 @@ describe('assess dataflow propagation mongoose.StringSchema', function () {
28
28
  validator: enumStub,
29
29
  }];
30
30
  };
31
+ MockSchemaString.prototype.castForQuery = function($c, v) {
32
+ return v;
33
+ };
31
34
  MockSchemaString.prototype.enum = function () {
32
35
  return this;
33
36
  };
@@ -39,7 +42,7 @@ describe('assess dataflow propagation mongoose.StringSchema', function () {
39
42
 
40
43
  tracker = core.assess.dataflow.tracker;
41
44
  core.assess.dataflow.propagation.mongooseInstrumentation.schemaString.install();
42
- core.depHooks.resolve.yield(MockSchemaString);
45
+ core.depHooks.resolve.yield(MockSchemaString, { version: '7.5.3' });
43
46
  });
44
47
 
45
48
  afterEach(function () {
@@ -60,6 +63,42 @@ describe('assess dataflow propagation mongoose.StringSchema', function () {
60
63
  });
61
64
  });
62
65
 
66
+ describe('SchemaString#castForQuery()', function () {
67
+ it('adds STRING_TYPE_CHECKED when called directly on a value', function () {
68
+ simulateRequestScope(function () {
69
+ const str = trackString('foo');
70
+ const strInfo = tracker.getData(str);
71
+
72
+ mockSchemaString.castForQuery(null, str);
73
+
74
+ expect(strInfo).to.deep.include({
75
+ value: 'foo',
76
+ addedTags: ['STRING_TYPE_CHECKED'],
77
+ tags: { UNTRUSTED: [0, 2], STRING_TYPE_CHECKED: [0, 2] },
78
+ });
79
+ });
80
+ });
81
+
82
+ it('does not add STRING_TYPE_CHECKED when called with a conditional', function () {
83
+ simulateRequestScope(function () {
84
+ const str = trackString('foo');
85
+ const strInfo = tracker.getData(str);
86
+
87
+ mockSchemaString.castForQuery('$ne', str);
88
+
89
+ expect(strInfo).to.deep.include({
90
+ value: 'foo',
91
+ tags: { UNTRUSTED: [0, 2] },
92
+ });
93
+ expect(strInfo).not.to.deep.include({
94
+ addedTags: ['STRING_TYPE_CHECKED'],
95
+ tags: { UNTRUSTED: [0, 2], STRING_TYPE_CHECKED: [0, 2] },
96
+ });
97
+
98
+ });
99
+ });
100
+ });
101
+
63
102
  it('SchemaString.doValidate adds STRING_TYPE_CHECKED tag', function () {
64
103
  return new Promise((resolve) => {
65
104
  simulateRequestScope(function () {
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  return patcher.patch(mustache, '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;
@@ -92,6 +92,7 @@ module.exports = function(core) {
92
92
  patcher.patch(mysql, 'escape', {
93
93
  name: `${lib}.escape`,
94
94
  patchType,
95
+ usePerf: 'sync',
95
96
  post: createPostHook(`${lib}.escape`, `${createModuleLabel(lib, version)}`)
96
97
  });
97
98
  });
@@ -101,6 +102,7 @@ module.exports = function(core) {
101
102
  patcher.patch(mysqlConnection.prototype, 'escape', {
102
103
  name: 'mysql.Connection.prototype.escape',
103
104
  patchType,
105
+ usePerf: 'sync',
104
106
  post: createPostHook('mysql/lib/Connection.escape', `[${createModuleLabel('mysql', version)}].Connection`)
105
107
  });
106
108
  });
@@ -109,6 +111,7 @@ module.exports = function(core) {
109
111
  patcher.patch(mysqlConnection.prototype, 'escape', {
110
112
  name: 'mysql.Connection.prototype.escape',
111
113
  patchType,
114
+ usePerf: 'sync',
112
115
  post: createPostHook('mysql2/lib/connection.Connection.escape', `[${createModuleLabel('mysql2', version)}].Connection`)
113
116
  });
114
117
  });
@@ -36,6 +36,7 @@ module.exports = function (core) {
36
36
  patcher.patch(global, 'parseInt', {
37
37
  name,
38
38
  patchType,
39
+ usePerf: 'sync',
39
40
  post(data) {
40
41
  const { args: [value], result } = data;
41
42
  if (
@@ -40,6 +40,7 @@ module.exports = function(core) {
40
40
  patcher.patch(path[os], 'basename', {
41
41
  name: `path.${os}.basename`,
42
42
  patchType,
43
+ usePerf: 'sync',
43
44
  post(data) {
44
45
  const { args: origArgs, result, name, hooked, orig } = data;
45
46
 
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  patcher.patch(path[os], 'dirname', {
40
40
  name: `path.${os}.dirname`,
41
41
  patchType,
42
+ usePerf: 'sync',
42
43
  post(data) {
43
44
  const { args, result, name, hooked, orig } = data;
44
45
 
@@ -41,6 +41,7 @@ module.exports = function(core) {
41
41
  patcher.patch(path[os], 'extname', {
42
42
  name: `path.${os}.extname`,
43
43
  patchType,
44
+ usePerf: 'sync',
44
45
  post(data) {
45
46
  const { args, result, name, hooked, orig } = data;
46
47
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -41,6 +41,7 @@ module.exports = function(core) {
41
41
  patcher.patch(path[os], 'format', {
42
42
  name: `path.${os}.format`,
43
43
  patchType,
44
+ usePerf: 'sync',
44
45
  post(data) {
45
46
  const { args, result, name: patchName, hooked, orig } = data;
46
47
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -43,6 +43,7 @@ module.exports = function(core) {
43
43
  patcher.patch(path[os], method, {
44
44
  name,
45
45
  patchType,
46
+ usePerf: 'sync',
46
47
  post(data) {
47
48
  const { args: origArgs, result, hooked, orig } = data;
48
49
 
@@ -39,6 +39,7 @@ module.exports = function(core) {
39
39
  patcher.patch(path[os], 'normalize', {
40
40
  name: `path.${os}.normalize`,
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;
@@ -26,7 +26,7 @@ module.exports = function(core) {
26
26
  patcher,
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
  },
@@ -41,6 +41,7 @@ module.exports = function(core) {
41
41
  patcher.patch(path[os], 'parse', {
42
42
  name: `path.${os}.parse`,
43
43
  patchType,
44
+ usePerf: 'sync',
44
45
  post(data) {
45
46
  const { args, result, name: patchName, hooked, orig } = data;
46
47
  if (!result || !getSourceContext(PROPAGATOR)) return;