@contrast/assess 1.35.0 → 1.37.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 (169) hide show
  1. package/lib/crypto-analysis/install/crypto.js +1 -1
  2. package/lib/dataflow/propagation/install/JSON/parse-fn.js +1 -1
  3. package/lib/dataflow/propagation/install/JSON/parse.js +3 -2
  4. package/lib/dataflow/propagation/install/JSON/parse.test.js +2 -2
  5. package/lib/dataflow/propagation/install/JSON/stringify.js +11 -10
  6. package/lib/dataflow/propagation/install/JSON/stringify.test.js +3 -3
  7. package/lib/dataflow/propagation/install/array-prototype-join.js +4 -3
  8. package/lib/dataflow/propagation/install/array-prototype-join.test.js +3 -3
  9. package/lib/dataflow/propagation/install/buffer.js +2 -3
  10. package/lib/dataflow/propagation/install/contrast-methods/tag.test.js +2 -2
  11. package/lib/dataflow/propagation/install/decode-uri-component.js +5 -8
  12. package/lib/dataflow/propagation/install/decode-uri-component.test.js +1 -1
  13. package/lib/dataflow/propagation/install/ejs/escape-xml.js +6 -9
  14. package/lib/dataflow/propagation/install/ejs/escape-xml.test.js +2 -2
  15. package/lib/dataflow/propagation/install/ejs/template.js +2 -2
  16. package/lib/dataflow/propagation/install/encode-uri.js +4 -6
  17. package/lib/dataflow/propagation/install/encode-uri.test.js +2 -2
  18. package/lib/dataflow/propagation/install/escape-html.js +5 -8
  19. package/lib/dataflow/propagation/install/escape-html.test.js +3 -3
  20. package/lib/dataflow/propagation/install/escape.js +5 -8
  21. package/lib/dataflow/propagation/install/escape.test.js +2 -2
  22. package/lib/dataflow/propagation/install/fastify-send.js +3 -5
  23. package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +6 -9
  24. package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.test.js +1 -1
  25. package/lib/dataflow/propagation/install/joi/boolean.js +50 -52
  26. package/lib/dataflow/propagation/install/joi/expression.js +3 -10
  27. package/lib/dataflow/propagation/install/joi/index.js +98 -101
  28. package/lib/dataflow/propagation/install/joi/keys.js +10 -5
  29. package/lib/dataflow/propagation/install/joi/number.js +50 -52
  30. package/lib/dataflow/propagation/install/joi/string-schema.js +9 -14
  31. package/lib/dataflow/propagation/install/joi/utils.js +7 -4
  32. package/lib/dataflow/propagation/install/joi/values.js +5 -7
  33. package/lib/dataflow/propagation/install/mongoose/schema-map.js +5 -4
  34. package/lib/dataflow/propagation/install/mongoose/schema-map.test.js +4 -4
  35. package/lib/dataflow/propagation/install/mongoose/schema-mixed.js +5 -4
  36. package/lib/dataflow/propagation/install/mongoose/schema-mixed.test.js +4 -5
  37. package/lib/dataflow/propagation/install/mongoose/schema-string.js +99 -5
  38. package/lib/dataflow/propagation/install/mongoose/schema-string.test.js +41 -2
  39. package/lib/dataflow/propagation/install/mustache-escape.js +5 -8
  40. package/lib/dataflow/propagation/install/mustache-escape.test.js +2 -2
  41. package/lib/dataflow/propagation/install/mysql-connection-escape.js +5 -8
  42. package/lib/dataflow/propagation/install/mysql-connection-escape.test.js +2 -2
  43. package/lib/dataflow/propagation/install/parse-int.js +3 -3
  44. package/lib/dataflow/propagation/install/path/basename.js +7 -12
  45. package/lib/dataflow/propagation/install/path/basename.test.js +2 -2
  46. package/lib/dataflow/propagation/install/path/common.js +2 -2
  47. package/lib/dataflow/propagation/install/path/dirname.js +5 -10
  48. package/lib/dataflow/propagation/install/path/dirname.test.js +2 -2
  49. package/lib/dataflow/propagation/install/path/extname.js +6 -11
  50. package/lib/dataflow/propagation/install/path/extname.test.js +2 -2
  51. package/lib/dataflow/propagation/install/path/format.js +7 -13
  52. package/lib/dataflow/propagation/install/path/format.test.js +2 -2
  53. package/lib/dataflow/propagation/install/path/join-and-resolve.js +7 -12
  54. package/lib/dataflow/propagation/install/path/join-and-resolve.test.js +2 -2
  55. package/lib/dataflow/propagation/install/path/normalize.js +4 -11
  56. package/lib/dataflow/propagation/install/path/normalize.test.js +2 -2
  57. package/lib/dataflow/propagation/install/path/parse.js +3 -8
  58. package/lib/dataflow/propagation/install/path/parse.test.js +2 -2
  59. package/lib/dataflow/propagation/install/path/relative.js +5 -11
  60. package/lib/dataflow/propagation/install/path/relative.test.js +2 -2
  61. package/lib/dataflow/propagation/install/path/toNamespacedPath.js +5 -11
  62. package/lib/dataflow/propagation/install/path/toNamespacedPath.test.js +2 -2
  63. package/lib/dataflow/propagation/install/pug/index.js +8 -3
  64. package/lib/dataflow/propagation/install/pug-runtime-escape.js +5 -8
  65. package/lib/dataflow/propagation/install/pug-runtime-escape.test.js +1 -1
  66. package/lib/dataflow/propagation/install/querystring/escape.js +3 -3
  67. package/lib/dataflow/propagation/install/querystring/parse.js +7 -11
  68. package/lib/dataflow/propagation/install/querystring/stringify.js +3 -3
  69. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +4 -3
  70. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.test.js +5 -3
  71. package/lib/dataflow/propagation/install/send.js +5 -10
  72. package/lib/dataflow/propagation/install/sequelize/query-generator.js +3 -4
  73. package/lib/dataflow/propagation/install/sequelize/sql-string.js +8 -12
  74. package/lib/dataflow/propagation/install/sequelize/sql-string.test.js +2 -13
  75. package/lib/dataflow/propagation/install/sql-template-strings.js +3 -5
  76. package/lib/dataflow/propagation/install/sql-template-strings.test.js +2 -2
  77. package/lib/dataflow/propagation/install/string/concat.js +2 -1
  78. package/lib/dataflow/propagation/install/string/concat.test.js +15 -2
  79. package/lib/dataflow/propagation/install/string/format-methods.js +4 -2
  80. package/lib/dataflow/propagation/install/string/format-methods.test.js +15 -2
  81. package/lib/dataflow/propagation/install/string/html-methods.js +1 -1
  82. package/lib/dataflow/propagation/install/string/html-methods.test.js +15 -2
  83. package/lib/dataflow/propagation/install/string/index.js +2 -2
  84. package/lib/dataflow/propagation/install/string/match-all.js +2 -1
  85. package/lib/dataflow/propagation/install/string/match-all.test.js +13 -0
  86. package/lib/dataflow/propagation/install/string/match.js +11 -10
  87. package/lib/dataflow/propagation/install/string/match.test.js +13 -0
  88. package/lib/dataflow/propagation/install/string/replace.js +15 -9
  89. package/lib/dataflow/propagation/install/string/replace.test.js +13 -0
  90. package/lib/dataflow/propagation/install/string/slice.js +2 -1
  91. package/lib/dataflow/propagation/install/string/slice.test.js +13 -0
  92. package/lib/dataflow/propagation/install/string/split.js +2 -1
  93. package/lib/dataflow/propagation/install/string/split.test.js +13 -0
  94. package/lib/dataflow/propagation/install/string/substring.js +2 -1
  95. package/lib/dataflow/propagation/install/string/substring.test.js +13 -0
  96. package/lib/dataflow/propagation/install/string/trim.js +4 -1
  97. package/lib/dataflow/propagation/install/string/trim.test.js +13 -0
  98. package/lib/dataflow/propagation/install/unescape.js +5 -8
  99. package/lib/dataflow/propagation/install/unescape.test.js +2 -2
  100. package/lib/dataflow/propagation/install/url/domain-parsers.js +4 -5
  101. package/lib/dataflow/propagation/install/url/domain-parsers.test.js +2 -2
  102. package/lib/dataflow/propagation/install/url/parse.js +3 -2
  103. package/lib/dataflow/propagation/install/url/parse.test.js +2 -2
  104. package/lib/dataflow/propagation/install/url/searchParams.js +5 -5
  105. package/lib/dataflow/propagation/install/url/searchParams.test.js +2 -2
  106. package/lib/dataflow/propagation/install/url/url.js +6 -3
  107. package/lib/dataflow/propagation/install/url/url.test.js +2 -2
  108. package/lib/dataflow/propagation/install/util-format.js +7 -6
  109. package/lib/dataflow/propagation/install/util-format.test.js +2 -2
  110. package/lib/dataflow/propagation/install/validator/hooks.js +7 -2
  111. package/lib/dataflow/sinks/install/child-process.js +1 -1
  112. package/lib/dataflow/sinks/install/child-process.test.js +1 -1
  113. package/lib/dataflow/sinks/install/fs.js +1 -1
  114. package/lib/dataflow/sinks/install/fs.test.js +1 -1
  115. package/lib/dataflow/sinks/install/function.js +1 -1
  116. package/lib/dataflow/sinks/install/http/request.js +2 -1
  117. package/lib/dataflow/sinks/install/http/request.test.js +1 -1
  118. package/lib/dataflow/sinks/install/http/server-response.test.js +3 -5
  119. package/lib/dataflow/sinks/install/restify.js +1 -1
  120. package/lib/dataflow/sinks/install/vm.js +4 -2
  121. package/lib/dataflow/sinks/install/vm.test.js +1 -1
  122. package/lib/dataflow/sources/handler.js +5 -2
  123. package/lib/dataflow/sources/install/body-parser1.test.js +4 -4
  124. package/lib/dataflow/sources/install/busboy.js +8 -3
  125. package/lib/dataflow/sources/install/busboy.test.js +2 -2
  126. package/lib/dataflow/sources/install/cookie-parser1.test.js +2 -2
  127. package/lib/dataflow/sources/install/express/params.js +14 -11
  128. package/lib/dataflow/sources/install/express/params.test.js +5 -7
  129. package/lib/dataflow/sources/install/express/parsedUrl.js +3 -2
  130. package/lib/dataflow/sources/install/fastify/fastify.js +7 -6
  131. package/lib/dataflow/sources/install/fastify/fastify.test.js +2 -2
  132. package/lib/dataflow/sources/install/formidable1.js +7 -6
  133. package/lib/dataflow/sources/install/formidable1.test.js +2 -2
  134. package/lib/dataflow/sources/install/hapi/hapi.js +8 -10
  135. package/lib/dataflow/sources/install/hapi/hapi.test.js +0 -1
  136. package/lib/dataflow/sources/install/http.js +20 -16
  137. package/lib/dataflow/sources/install/http.test.js +28 -34
  138. package/lib/dataflow/sources/install/koa/koa-bodyparsers.js +7 -7
  139. package/lib/dataflow/sources/install/koa/koa-bodyparsers.test.js +3 -4
  140. package/lib/dataflow/sources/install/koa/koa-multer.js +8 -4
  141. package/lib/dataflow/sources/install/koa/koa-routers.js +7 -6
  142. package/lib/dataflow/sources/install/koa/koa-routers.test.js +2 -2
  143. package/lib/dataflow/sources/install/koa/koa2.js +7 -3
  144. package/lib/dataflow/sources/install/koa/koa2.test.js +1 -1
  145. package/lib/dataflow/sources/install/multer1.js +6 -2
  146. package/lib/dataflow/sources/install/qs6.js +1 -1
  147. package/lib/dataflow/sources/install/querystring.js +1 -1
  148. package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.js +1 -4
  149. package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.test.js +6 -8
  150. package/lib/dataflow/sources/install/restify/jsonBodyParser.js +0 -1
  151. package/lib/dataflow/sources/install/restify/jsonBodyParser.test.js +4 -8
  152. package/lib/dataflow/sources/install/restify/router.test.js +2 -2
  153. package/lib/dataflow/tag-utils.js +1 -1
  154. package/lib/dataflow/tracker.js +1 -1
  155. package/lib/dataflow/utils/is-safe-content-type.js +3 -2
  156. package/lib/event-factory.js +4 -4
  157. package/lib/get-policy.js +2 -2
  158. package/lib/index.js +18 -7
  159. package/lib/index.test.js +4 -0
  160. package/lib/make-source-context.js +37 -28
  161. package/lib/make-source-context.test.js +7 -7
  162. package/lib/response-scanning/handlers/index.js +7 -5
  163. package/lib/response-scanning/handlers/utils.js +11 -8
  164. package/lib/response-scanning/install/http.js +1 -1
  165. package/lib/sampler.js +136 -0
  166. package/lib/sampler.test.js +296 -0
  167. package/lib/session-configuration/install/express-session.js +1 -1
  168. package/lib/session-configuration/install/fastify-cookie.js +1 -1
  169. package/package.json +10 -10
@@ -23,9 +23,9 @@ const { patchType } = require('../../common');
23
23
  module.exports = function(core) {
24
24
  const {
25
25
  depHooks,
26
- scopes: { sources, instrumentation },
27
26
  patcher,
28
27
  assess: {
28
+ getSourceContext,
29
29
  inspect, // todo: remove
30
30
  eventFactory: { createPropagationEvent },
31
31
  dataflow: { tracker },
@@ -40,70 +40,68 @@ module.exports = function(core) {
40
40
  */
41
41
  function instrumentJoiBoolean(boolean) {
42
42
  const def = Object.getPrototypeOf(boolean)?._definition;
43
- def &&
44
- patcher.patch(def.coerce, 'method', {
45
- name: 'joi.boolean.coerce',
46
- patchType,
47
- post(data) {
48
- if (
49
- !data.result?.value ||
50
- typeof data.result.value !== 'boolean' ||
51
- !sources.getStore()?.assess ||
52
- instrumentation.isLocked()
53
- )
54
- return;
43
+ if (!def?.coerce) return;
55
44
 
56
- const argInfo = tracker.getData(data.args[0]);
45
+ patcher.patch(def.coerce, 'method', {
46
+ name: 'joi.boolean.coerce',
47
+ patchType,
48
+ post(data) {
49
+ if (
50
+ !data.result?.value ||
51
+ typeof data.result.value !== 'boolean' ||
52
+ !getSourceContext()
53
+ ) return;
57
54
 
58
- if (!argInfo) return;
55
+ const argInfo = tracker.getData(data.args[0]);
56
+ if (!argInfo) return;
59
57
 
60
- const event = createPropagationEvent({
61
- name: 'Joi.boolean.coerce',
62
- moduleName: 'joi',
63
- methodName: 'boolean.coerce',
64
- history: [{ ...argInfo }],
65
- object: {
58
+ const event = createPropagationEvent({
59
+ name: 'Joi.boolean.coerce',
60
+ moduleName: 'joi',
61
+ methodName: 'boolean.coerce',
62
+ history: [{ ...argInfo }],
63
+ object: {
64
+ tracked: false,
65
+ value: 'Joi.boolean',
66
+ },
67
+ args: [
68
+ { tracked: true, value: argInfo.value },
69
+ {
66
70
  tracked: false,
67
- value: 'Joi.boolean',
68
- },
69
- args: [
70
- { tracked: true, value: argInfo.value },
71
- {
72
- tracked: false,
73
- value: {
74
- ...inspect(data.args[1]),
75
- original: argInfo.value,
76
- },
71
+ value: {
72
+ ...inspect(data.args[1]),
73
+ original: argInfo.value,
77
74
  },
78
- ],
79
- result: {
80
- tracked: false,
81
- value: data.result,
82
- },
83
- source: 'P0',
84
- tags: {
85
- ...argInfo.tags,
86
- [ALPHANUM_SPACE_HYPHEN]: [0, argInfo.value.length - 1],
87
- },
88
- target: 'P0',
89
- stacktraceOpts: {
90
- prependFrames: [data.orig],
91
75
  },
92
- });
76
+ ],
77
+ result: {
78
+ tracked: false,
79
+ value: data.result,
80
+ },
81
+ source: 'P0',
82
+ tags: {
83
+ ...argInfo.tags,
84
+ [ALPHANUM_SPACE_HYPHEN]: [0, argInfo.value.length - 1],
85
+ },
86
+ target: 'P0',
87
+ stacktraceOpts: {
88
+ prependFrames: [data.orig],
89
+ },
90
+ });
93
91
 
94
- if (event) {
95
- Object.assign(argInfo, event);
96
- }
97
- },
98
- });
92
+ if (event) {
93
+ Object.assign(argInfo, event);
94
+ }
95
+ },
96
+ });
99
97
  }
100
98
 
101
- return (core.assess.dataflow.propagation.joiInstrumentation.booleanCoerce = {
99
+ return core.assess.dataflow.propagation.joiInstrumentation.booleanCoerce = {
102
100
  install() {
103
101
  depHooks.resolve(
104
102
  { name: 'joi', file: 'lib/types/boolean.js', version: '>=17.0.0' },
105
103
  instrumentJoiBoolean
106
104
  );
107
105
  },
108
- });
106
+ };
109
107
  };
@@ -15,17 +15,15 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const {
19
- DataflowTag: { HTML_ENCODED },
20
- } = require('@contrast/common');
18
+ const { DataflowTag: { HTML_ENCODED } } = require('@contrast/common');
21
19
  const { patchType } = require('../../common');
22
20
 
23
21
  module.exports = function(core) {
24
22
  const {
25
23
  depHooks,
26
- scopes: { sources, instrumentation },
27
24
  patcher,
28
25
  assess: {
26
+ getSourceContext,
29
27
  inspect, // todo: remove
30
28
  eventFactory: { createPropagationEvent },
31
29
  dataflow: { tracker },
@@ -41,12 +39,7 @@ module.exports = function(core) {
41
39
  name: `joi.${method}`,
42
40
  patchType,
43
41
  post(data) {
44
- if (
45
- !data.result ||
46
- !sources.getStore()?.assess ||
47
- instrumentation.isLocked()
48
- )
49
- return;
42
+ if (!data.result || !getSourceContext()) return;
50
43
 
51
44
  const argInfo = tracker.getData(data.args[0]);
52
45
 
@@ -27,137 +27,134 @@ const { tagCustomValidatedString, handleReferences } = require('./utils');
27
27
  module.exports = function(core) {
28
28
  const {
29
29
  patcher,
30
- scopes: { sources, instrumentation },
31
30
  assess: {
31
+ getSourceContext,
32
32
  inspect, // todo: remove
33
33
  eventFactory: { createPropagationEvent },
34
34
  dataflow: { tracker },
35
35
  },
36
36
  } = core;
37
37
 
38
- const joiInstrumentation =
39
- (core.assess.dataflow.propagation.joiInstrumentation = {
40
- install() {
41
- callChildComponentMethodsSync(joiInstrumentation, 'install');
42
- },
43
- uninstall() {
44
- callChildComponentMethodsSync(joiInstrumentation, 'uninstall');
45
- },
46
- patchValidateAsync(parentObj, parentObjType) {
47
- patcher.patch(parentObj, 'validateAsync', {
48
- name: `Joi.${parentObjType}.validateAsync`,
49
- patchType,
50
- post(data) {
51
- const childNodes = data.obj?.$_terms.items?.length
52
- ? data.obj.$_terms.items
53
- : data.obj?.$_terms.keys?.length
54
- ? data.obj.$_terms.keys
55
- : null;
38
+ const joiInstrumentation = core.assess.dataflow.propagation.joiInstrumentation = {
39
+ install() {
40
+ callChildComponentMethodsSync(joiInstrumentation, 'install');
41
+ },
42
+ uninstall() {
43
+ callChildComponentMethodsSync(joiInstrumentation, 'uninstall');
44
+ },
45
+ patchValidateAsync(parentObj, parentObjType) {
46
+ patcher.patch(parentObj, 'validateAsync', {
47
+ name: `Joi.${parentObjType}.validateAsync`,
48
+ patchType,
49
+ post(data) {
50
+ const childNodes = data.obj?.$_terms.items?.length
51
+ ? data.obj.$_terms.items
52
+ : data.obj?.$_terms.keys?.length
53
+ ? data.obj.$_terms.keys
54
+ : null;
56
55
 
57
- if (
58
- (!childNodes && !data.obj?.$_terms?.externals?.length) ||
56
+ if (
57
+ (!childNodes && !data.obj?.$_terms?.externals?.length) ||
59
58
  (childNodes &&
60
- !childNodes.find((i) => {
61
- const schema = i?.schema || i;
62
- return schema.$_terms?.externals?.length;
63
- })) ||
59
+ !childNodes.find((i) => {
60
+ const schema = i?.schema || i;
61
+ return schema.$_terms?.externals?.length;
62
+ })) ||
64
63
  !core.config.assess.trust_custom_validators ||
65
- !sources.getStore()?.assess ||
66
- instrumentation.isLocked()
67
- )
68
- return;
64
+ !getSourceContext()
65
+ )
66
+ return;
69
67
 
70
- data.result.then((result) => {
71
- const metadata = {
72
- origFn: data.orig,
73
- methodName: parentObjType,
74
- target: 'R',
75
- };
68
+ data.result.then((result) => {
69
+ const metadata = {
70
+ origFn: data.orig,
71
+ methodName: parentObjType,
72
+ target: 'R',
73
+ };
76
74
 
77
- if (isString(result)) {
75
+ if (isString(result)) {
76
+ tagCustomValidatedString(
77
+ createPropagationEvent,
78
+ tracker.getData(result),
79
+ metadata
80
+ );
81
+ } else if (isNonEmptyObject(result)) {
82
+ traverseValues(result, (_path, _key, value) => {
78
83
  tagCustomValidatedString(
79
84
  createPropagationEvent,
80
- tracker.getData(result),
85
+ tracker.getData(value),
81
86
  metadata
82
87
  );
83
- } else if (isNonEmptyObject(result)) {
84
- traverseValues(result, (_path, _key, value) => {
85
- tagCustomValidatedString(
86
- createPropagationEvent,
87
- tracker.getData(value),
88
- metadata
89
- );
90
- });
91
- }
92
- })
93
- .catch(err => err);
94
- },
95
- });
96
- },
97
- patchCustomValidate(parentObj, objName) {
98
- patcher.patch(parentObj.rules.custom, 'validate', {
99
- name: `joi.${objName}.custom.valdiate`,
100
- patchType,
101
- post(data) {
102
- const {
103
- args: [input, schema],
104
- result,
105
- orig,
106
- } = data;
88
+ });
89
+ }
90
+ })
91
+ .catch(err => err);
92
+ },
93
+ });
94
+ },
95
+ patchCustomValidate(parentObj, objName) {
96
+ patcher.patch(parentObj.rules.custom, 'validate', {
97
+ name: `joi.${objName}.custom.valdiate`,
98
+ patchType,
99
+ post(data) {
100
+ const {
101
+ args: [input, schema],
102
+ result,
103
+ orig,
104
+ } = data;
107
105
 
108
- if (
109
- !result ||
106
+ if (
107
+ !result ||
110
108
  !input ||
111
109
  (result.value === input &&
112
- (result.messages?.source || result.local?.error)) ||
110
+ (result.messages?.source || result.local?.error)) ||
113
111
  !core.config.assess.trust_custom_validators ||
114
- !sources.getStore()?.assess ||
115
- instrumentation.isLocked()
116
- )
117
- return;
112
+ !getSourceContext()
113
+ )
114
+ return;
118
115
 
119
- const inspectedSecondArg = inspect(schema);
120
- const metadata = {
121
- origFn: orig,
122
- inspectedSecondArg,
123
- methodName: `${objName}.custom.validate`,
124
- target: 'R',
125
- };
126
- const validation = (trackingInfo) => {
116
+ const inspectedSecondArg = inspect(schema);
117
+ const metadata = {
118
+ origFn: orig,
119
+ inspectedSecondArg,
120
+ methodName: `${objName}.custom.validate`,
121
+ target: 'R',
122
+ };
123
+ const validation = (trackingInfo) => {
124
+ tagCustomValidatedString(
125
+ createPropagationEvent,
126
+ trackingInfo,
127
+ metadata
128
+ );
129
+ };
130
+
131
+ handleReferences(tracker, schema, validation);
132
+
133
+ if (isString(result)) {
134
+ validation(tracker.getData(result));
135
+ input === result &&
127
136
  tagCustomValidatedString(
128
137
  createPropagationEvent,
129
- trackingInfo,
130
- metadata
138
+ tracker.getData(input),
139
+ { ...metadata, target: 'P0' }
131
140
  );
132
- };
141
+ } else if (isNonEmptyObject(result)) {
142
+ traverseValues(result, (path, _key, value) => {
143
+ const argValue = path.reduce((obj, k) => obj[k] || obj, input);
133
144
 
134
- handleReferences(tracker, schema, validation);
135
-
136
- if (isString(result)) {
137
145
  validation(tracker.getData(result));
138
- input === result &&
146
+ argValue === value &&
139
147
  tagCustomValidatedString(
140
148
  createPropagationEvent,
141
- tracker.getData(input),
149
+ tracker.getData(argValue),
142
150
  { ...metadata, target: 'P0' }
143
151
  );
144
- } else if (isNonEmptyObject(result)) {
145
- traverseValues(result, (path, _key, value) => {
146
- const argValue = path.reduce((obj, k) => obj[k] || obj, input);
147
-
148
- validation(tracker.getData(result));
149
- argValue === value &&
150
- tagCustomValidatedString(
151
- createPropagationEvent,
152
- tracker.getData(argValue),
153
- { ...metadata, target: 'P0' }
154
- );
155
- });
156
- }
157
- },
158
- });
159
- },
160
- });
152
+ });
153
+ }
154
+ },
155
+ });
156
+ }
157
+ };
161
158
 
162
159
  require('./any')(core);
163
160
  require('./expression')(core);
@@ -17,7 +17,10 @@
17
17
 
18
18
  const {
19
19
  isNonEmptyObject,
20
- ArrayPrototypeJoin,
20
+ primordials: {
21
+ ArrayPrototypeJoin,
22
+ ArrayPrototypeSlice
23
+ }
21
24
  } = require('@contrast/common');
22
25
  const { patchType } = require('../../common');
23
26
 
@@ -25,6 +28,7 @@ module.exports = function(core) {
25
28
  const {
26
29
  depHooks,
27
30
  patcher,
31
+ assess: { getSourceContext }
28
32
  } = core;
29
33
 
30
34
  function addMetadata(schema, refTargetPath, refPath, isInReference) {
@@ -43,9 +47,9 @@ module.exports = function(core) {
43
47
  let path = ArrayPrototypeJoin.call(refTargetPath, '.');
44
48
 
45
49
  if (isInReference) {
46
- path = ArrayPrototypeJoin.call(refTargetPath.slice(0, -1), '.');
50
+ path = ArrayPrototypeJoin.call(ArrayPrototypeSlice.call(refTargetPath, 0, -1), '.');
47
51
  schema.__CONTRAST__.inReferenceTargets.add(path);
48
- refPath = refPath.slice(0, -1);
52
+ refPath = ArrayPrototypeSlice.call(refPath, 0, -1);
49
53
  }
50
54
 
51
55
  const refs = schema.__CONTRAST__.refTargets[path] || [];
@@ -119,7 +123,7 @@ module.exports = function(core) {
119
123
  }
120
124
  }
121
125
 
122
- return (core.assess.dataflow.propagation.joiInstrumentation.keys = {
126
+ return core.assess.dataflow.propagation.joiInstrumentation.keys = {
123
127
  install() {
124
128
  depHooks.resolve(
125
129
  { name: 'joi', file: 'lib/types/keys.js', version: '>=17.0.0' },
@@ -131,11 +135,12 @@ module.exports = function(core) {
131
135
  const [value] = data.args;
132
136
  const joi = data.obj.$_root;
133
137
 
138
+ if (!getSourceContext()) return;
134
139
  traverseSchemas(joi, value, value);
135
140
  },
136
141
  });
137
142
  }
138
143
  );
139
144
  },
140
- });
145
+ };
141
146
  };
@@ -23,9 +23,9 @@ const { patchType } = require('../../common');
23
23
  module.exports = function(core) {
24
24
  const {
25
25
  depHooks,
26
- scopes: { sources, instrumentation },
27
26
  patcher,
28
27
  assess: {
28
+ getSourceContext,
29
29
  inspect, // todo: remove
30
30
  eventFactory: { createPropagationEvent },
31
31
  dataflow: { tracker },
@@ -38,70 +38,68 @@ module.exports = function(core) {
38
38
  */
39
39
  function instrumentJoiNumber(number) {
40
40
  const def = Object.getPrototypeOf(number)?._definition;
41
- def &&
42
- patcher.patch(def.coerce, 'method', {
43
- name: 'joi.number.coerce',
44
- patchType,
45
- post(data) {
46
- if (
47
- !data.result?.value ||
48
- data.result.errors ||
49
- !sources.getStore()?.assess ||
50
- instrumentation.isLocked()
51
- )
52
- return;
41
+ if (!def?.coerce) return;
53
42
 
54
- const argInfo = tracker.getData(data.args[0]);
43
+ patcher.patch(def.coerce, 'method', {
44
+ name: 'joi.number.coerce',
45
+ patchType,
46
+ post(data) {
47
+ if (
48
+ !data.result?.value ||
49
+ data.result.errors ||
50
+ !getSourceContext()
51
+ ) return;
55
52
 
56
- if (!argInfo) return;
53
+ const argInfo = tracker.getData(data.args[0]);
54
+ if (!argInfo) return;
57
55
 
58
- const event = createPropagationEvent({
59
- name: 'Joi.number.coerce',
60
- moduleName: 'joi',
61
- methodName: 'number.coerce',
62
- history: [{ ...argInfo }],
63
- object: {
56
+ const event = createPropagationEvent({
57
+ name: 'Joi.number.coerce',
58
+ moduleName: 'joi',
59
+ methodName: 'number.coerce',
60
+ history: [{ ...argInfo }],
61
+ object: {
62
+ tracked: false,
63
+ value: 'Joi.number',
64
+ },
65
+ args: [
66
+ { tracked: true, value: argInfo.value },
67
+ {
64
68
  tracked: false,
65
- value: 'Joi.number',
66
- },
67
- args: [
68
- { tracked: true, value: argInfo.value },
69
- {
70
- tracked: false,
71
- value: {
72
- ...inspect(data.args[1]),
73
- original: argInfo.value,
74
- },
69
+ value: {
70
+ ...inspect(data.args[1]),
71
+ original: argInfo.value,
75
72
  },
76
- ],
77
- result: {
78
- tracked: false,
79
- value: data.result,
80
- },
81
- source: 'P0',
82
- tags: {
83
- ...argInfo.tags,
84
- [LIMITED_CHARS]: [0, argInfo.value.length - 1],
85
- },
86
- target: 'P0',
87
- stacktraceOpts: {
88
- prependFrames: [data.orig],
89
73
  },
90
- });
74
+ ],
75
+ result: {
76
+ tracked: false,
77
+ value: data.result,
78
+ },
79
+ source: 'P0',
80
+ tags: {
81
+ ...argInfo.tags,
82
+ [LIMITED_CHARS]: [0, argInfo.value.length - 1],
83
+ },
84
+ target: 'P0',
85
+ stacktraceOpts: {
86
+ prependFrames: [data.orig],
87
+ },
88
+ });
91
89
 
92
- if (event) {
93
- Object.assign(argInfo, event);
94
- }
95
- },
96
- });
90
+ if (event) {
91
+ Object.assign(argInfo, event);
92
+ }
93
+ },
94
+ });
97
95
  }
98
96
 
99
- return (core.assess.dataflow.propagation.joiInstrumentation.numberCoerce = {
97
+ return core.assess.dataflow.propagation.joiInstrumentation.numberCoerce = {
100
98
  install() {
101
99
  depHooks.resolve(
102
100
  { name: 'joi', file: 'lib/types/number.js', version: '>=17.0.0' },
103
101
  instrumentJoiNumber
104
102
  );
105
103
  },
106
- });
104
+ };
107
105
  };
@@ -39,17 +39,16 @@ const VALIDATORS = {
39
39
  module.exports = function(core) {
40
40
  const {
41
41
  depHooks,
42
- scopes: { sources, instrumentation },
43
42
  patcher,
44
43
  assess: {
44
+ getSourceContext,
45
45
  inspect, // todo: remove
46
46
  eventFactory: { createPropagationEvent },
47
47
  dataflow: {
48
48
  tracker, propagation: {
49
49
  joiInstrumentation
50
50
  }
51
- },
52
-
51
+ }
53
52
  },
54
53
  } = core;
55
54
 
@@ -113,10 +112,8 @@ module.exports = function(core) {
113
112
  !input ||
114
113
  (validatorName !== 'validate' && typeof data.result !== 'string') ||
115
114
  (validatorName === 'validate' && data.result) ||
116
- !sources.getStore()?.assess ||
117
- instrumentation.isLocked()
118
- )
119
- return;
115
+ !getSourceContext()
116
+ ) return;
120
117
 
121
118
  const inspectedSchema = inspect(schema);
122
119
  const validation = definePropagation(
@@ -147,10 +144,8 @@ module.exports = function(core) {
147
144
  !args[0] ||
148
145
  // currently, we are losing track of coerced isoDate only
149
146
  !args[1].schema.$_getRule('isoDate') ||
150
- !sources.getStore()?.assess ||
151
- instrumentation.isLocked()
152
- )
153
- return;
147
+ !getSourceContext()
148
+ ) return;
154
149
 
155
150
  const argInfo = tracker.getData(args[0]);
156
151
 
@@ -194,7 +189,7 @@ module.exports = function(core) {
194
189
  });
195
190
  }
196
191
 
197
- return (joiInstrumentation.stringSchema = {
192
+ return joiInstrumentation.stringSchema = {
198
193
  install() {
199
194
  depHooks.resolve(
200
195
  { name: 'joi', file: 'lib/types/string.js', version: '>=17.0.0' },
@@ -229,6 +224,6 @@ module.exports = function(core) {
229
224
  }
230
225
  }
231
226
  );
232
- },
233
- });
227
+ }
228
+ };
234
229
  };
@@ -16,8 +16,11 @@
16
16
  'use strict';
17
17
 
18
18
  const {
19
- StringPrototypeSplit,
20
- ArrayPrototypeJoin,
19
+ primordials: {
20
+ StringPrototypeSplit,
21
+ ArrayPrototypeJoin,
22
+ ArrayPrototypeSlice,
23
+ },
21
24
  DataflowTag: { CUSTOM_VALIDATED }
22
25
  } = require('@contrast/common');
23
26
 
@@ -75,10 +78,10 @@ function tagCustomValidatedString(createPropagationEvent, strInfo, metadata) {
75
78
  function handleReferences(tracker, schema, validationFn) {
76
79
  const contrastData = schema?.schema?.__CONTRAST__;
77
80
  let refTargetPath = contrastData && ArrayPrototypeJoin.call(schema.state.path, '.');
78
- const inReferenceTargetPath = contrastData && ArrayPrototypeJoin.call(schema.state.path.slice(0, -1), '.');
81
+ const inReferenceTargetPath = contrastData && ArrayPrototypeJoin.call(ArrayPrototypeSlice.call(schema.state.path, 0, -1), '.');
79
82
  if (contrastData?.inReferenceTargets.has(inReferenceTargetPath)) {
80
83
  refTargetPath = ArrayPrototypeJoin.call(
81
- schema.state.path.slice(0, -1),
84
+ ArrayPrototypeSlice.call(schema.state.path, 0, -1),
82
85
  '.'
83
86
  );
84
87
  }