@contrast/assess 1.34.0 → 1.36.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 (171) 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 +3 -4
  38. package/lib/dataflow/propagation/install/mustache-escape.js +5 -8
  39. package/lib/dataflow/propagation/install/mustache-escape.test.js +2 -2
  40. package/lib/dataflow/propagation/install/mysql-connection-escape.js +5 -8
  41. package/lib/dataflow/propagation/install/mysql-connection-escape.test.js +2 -2
  42. package/lib/dataflow/propagation/install/parse-int.js +3 -3
  43. package/lib/dataflow/propagation/install/path/basename.js +7 -12
  44. package/lib/dataflow/propagation/install/path/basename.test.js +2 -2
  45. package/lib/dataflow/propagation/install/path/common.js +2 -2
  46. package/lib/dataflow/propagation/install/path/dirname.js +5 -10
  47. package/lib/dataflow/propagation/install/path/dirname.test.js +2 -2
  48. package/lib/dataflow/propagation/install/path/extname.js +6 -11
  49. package/lib/dataflow/propagation/install/path/extname.test.js +2 -2
  50. package/lib/dataflow/propagation/install/path/format.js +7 -13
  51. package/lib/dataflow/propagation/install/path/format.test.js +2 -2
  52. package/lib/dataflow/propagation/install/path/join-and-resolve.js +7 -12
  53. package/lib/dataflow/propagation/install/path/join-and-resolve.test.js +2 -2
  54. package/lib/dataflow/propagation/install/path/normalize.js +4 -11
  55. package/lib/dataflow/propagation/install/path/normalize.test.js +2 -2
  56. package/lib/dataflow/propagation/install/path/parse.js +3 -8
  57. package/lib/dataflow/propagation/install/path/parse.test.js +2 -2
  58. package/lib/dataflow/propagation/install/path/relative.js +5 -11
  59. package/lib/dataflow/propagation/install/path/relative.test.js +2 -2
  60. package/lib/dataflow/propagation/install/path/toNamespacedPath.js +5 -11
  61. package/lib/dataflow/propagation/install/path/toNamespacedPath.test.js +2 -2
  62. package/lib/dataflow/propagation/install/pug/index.js +8 -3
  63. package/lib/dataflow/propagation/install/pug-runtime-escape.js +5 -8
  64. package/lib/dataflow/propagation/install/pug-runtime-escape.test.js +1 -1
  65. package/lib/dataflow/propagation/install/querystring/escape.js +3 -3
  66. package/lib/dataflow/propagation/install/querystring/parse.js +7 -11
  67. package/lib/dataflow/propagation/install/querystring/stringify.js +3 -3
  68. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +4 -3
  69. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.test.js +5 -3
  70. package/lib/dataflow/propagation/install/send.js +5 -10
  71. package/lib/dataflow/propagation/install/sequelize/query-generator.js +3 -4
  72. package/lib/dataflow/propagation/install/sequelize/sql-string.js +8 -12
  73. package/lib/dataflow/propagation/install/sequelize/sql-string.test.js +2 -13
  74. package/lib/dataflow/propagation/install/sql-template-strings.js +3 -5
  75. package/lib/dataflow/propagation/install/sql-template-strings.test.js +2 -2
  76. package/lib/dataflow/propagation/install/string/concat.js +2 -1
  77. package/lib/dataflow/propagation/install/string/concat.test.js +15 -2
  78. package/lib/dataflow/propagation/install/string/format-methods.js +4 -2
  79. package/lib/dataflow/propagation/install/string/format-methods.test.js +15 -2
  80. package/lib/dataflow/propagation/install/string/html-methods.js +1 -1
  81. package/lib/dataflow/propagation/install/string/html-methods.test.js +15 -2
  82. package/lib/dataflow/propagation/install/string/index.js +2 -2
  83. package/lib/dataflow/propagation/install/string/match-all.js +2 -1
  84. package/lib/dataflow/propagation/install/string/match-all.test.js +13 -0
  85. package/lib/dataflow/propagation/install/string/match.js +11 -10
  86. package/lib/dataflow/propagation/install/string/match.test.js +13 -0
  87. package/lib/dataflow/propagation/install/string/replace.js +15 -9
  88. package/lib/dataflow/propagation/install/string/replace.test.js +13 -0
  89. package/lib/dataflow/propagation/install/string/slice.js +2 -1
  90. package/lib/dataflow/propagation/install/string/slice.test.js +13 -0
  91. package/lib/dataflow/propagation/install/string/split.js +2 -1
  92. package/lib/dataflow/propagation/install/string/split.test.js +13 -0
  93. package/lib/dataflow/propagation/install/string/substring.js +2 -1
  94. package/lib/dataflow/propagation/install/string/substring.test.js +13 -0
  95. package/lib/dataflow/propagation/install/string/trim.js +4 -1
  96. package/lib/dataflow/propagation/install/string/trim.test.js +13 -0
  97. package/lib/dataflow/propagation/install/unescape.js +5 -8
  98. package/lib/dataflow/propagation/install/unescape.test.js +2 -2
  99. package/lib/dataflow/propagation/install/url/domain-parsers.js +4 -5
  100. package/lib/dataflow/propagation/install/url/domain-parsers.test.js +2 -2
  101. package/lib/dataflow/propagation/install/url/parse.js +3 -2
  102. package/lib/dataflow/propagation/install/url/parse.test.js +2 -2
  103. package/lib/dataflow/propagation/install/url/searchParams.js +5 -5
  104. package/lib/dataflow/propagation/install/url/searchParams.test.js +2 -2
  105. package/lib/dataflow/propagation/install/url/url.js +6 -3
  106. package/lib/dataflow/propagation/install/url/url.test.js +2 -2
  107. package/lib/dataflow/propagation/install/util-format.js +7 -6
  108. package/lib/dataflow/propagation/install/util-format.test.js +2 -2
  109. package/lib/dataflow/propagation/install/validator/hooks.js +7 -2
  110. package/lib/dataflow/sinks/install/child-process.js +1 -1
  111. package/lib/dataflow/sinks/install/child-process.test.js +1 -1
  112. package/lib/dataflow/sinks/install/fs.js +1 -1
  113. package/lib/dataflow/sinks/install/fs.test.js +1 -1
  114. package/lib/dataflow/sinks/install/function.js +1 -1
  115. package/lib/dataflow/sinks/install/http/request.js +2 -1
  116. package/lib/dataflow/sinks/install/http/request.test.js +1 -1
  117. package/lib/dataflow/sinks/install/http/server-response.test.js +3 -5
  118. package/lib/dataflow/sinks/install/restify.js +1 -1
  119. package/lib/dataflow/sinks/install/vm.js +4 -2
  120. package/lib/dataflow/sinks/install/vm.test.js +1 -1
  121. package/lib/dataflow/sources/handler.js +6 -3
  122. package/lib/dataflow/sources/handler.test.js +38 -0
  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/event-factory.test.js +19 -14
  158. package/lib/get-policy.js +2 -2
  159. package/lib/index.d.ts +11 -6
  160. package/lib/index.js +18 -7
  161. package/lib/index.test.js +4 -0
  162. package/lib/make-source-context.js +37 -28
  163. package/lib/make-source-context.test.js +7 -7
  164. package/lib/response-scanning/handlers/index.js +7 -5
  165. package/lib/response-scanning/handlers/utils.js +11 -8
  166. package/lib/response-scanning/install/http.js +1 -1
  167. package/lib/sampler.js +136 -0
  168. package/lib/sampler.test.js +296 -0
  169. package/lib/session-configuration/install/express-session.js +1 -1
  170. package/lib/session-configuration/install/fastify-cookie.js +1 -1
  171. package/package.json +10 -10
@@ -15,17 +15,15 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const {
19
- DataflowTag: { SQL_ENCODED }
20
- } = require('@contrast/common');
18
+ const { DataflowTag: { SQL_ENCODED } } = require('@contrast/common');
21
19
  const { patchType, createModuleLabel } = require('../common');
22
20
 
23
21
  module.exports = function(core) {
24
22
  const {
25
- scopes: { sources, instrumentation },
26
23
  patcher,
27
24
  depHooks,
28
25
  assess: {
26
+ getSourceContext,
29
27
  eventFactory: { createPropagationEvent },
30
28
  dataflow: { tracker }
31
29
  }
@@ -41,7 +39,7 @@ module.exports = function(core) {
41
39
  patchType,
42
40
  post(data) {
43
41
  const { args, result, hooked, orig } = data;
44
- if (!result || !args[0] || !sources.getStore()?.assess || instrumentation.isLocked()) return;
42
+ if (!result || !args[0] || !getSourceContext()) return;
45
43
 
46
44
  const argInfo = tracker.getData(args[0]);
47
45
 
@@ -80,12 +80,12 @@ describe('assess dataflow propagation sql-template-strings', function () {
80
80
  });
81
81
  });
82
82
 
83
- it('will not propagate if there is no assess context', function () {
83
+ it('will not propagate if there is no assess policy in request context', function () {
84
84
  simulateRequestScope(function () {
85
85
  const value = trackString('foo');
86
86
  const result = mockSqlTemplateStrings.SQL(['foo', value].join());
87
87
  expect(tracker.getData(result.strings.toString())).to.be.null;
88
- }, {});
88
+ }, { assess: { policy: null } });
89
89
  });
90
90
 
91
91
  it('will not propagate if there instrumentation is locked', function () {
@@ -15,7 +15,7 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const { ArrayPrototypeJoin } = require('@contrast/common');
18
+ const { primordials: { ArrayPrototypeJoin } } = require('@contrast/common');
19
19
  const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
20
20
  const { createAppendTags, getAdjustedUntrackedValue } = require('../../../tag-utils');
21
21
  const { patchType } = require('../../common');
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(String.prototype, 'concat', {
38
38
  name,
39
39
  patchType,
40
+ usePerf: true,
40
41
  post(data) {
41
42
  const { obj, result, hooked, orig } = data;
42
43
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string concat', function () {
8
8
  let core, trackString, simulateRequestScope, tracker;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -23,6 +24,18 @@ describe('assess dataflow propagation string concat', function () {
23
24
  sinon.resetHistory();
24
25
  });
25
26
 
27
+ // eslint-disable-next-line mocha/no-sibling-hooks
28
+ afterEach(function() {
29
+ core.Perf.fromAllToMap('patcher', allPatcher);
30
+ });
31
+
32
+ after(function() {
33
+ const stats = core.Perf.getStats(allPatcher);
34
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
35
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
36
+ }
37
+ });
38
+
26
39
  [
27
40
  {
28
41
  str: 'foo',
@@ -112,12 +125,12 @@ describe('assess dataflow propagation string concat', function () {
112
125
  });
113
126
  });
114
127
 
115
- it('will not propagate if there is no assess context', function () {
128
+ it('will not propagate if there is no assess policy in request context', function () {
116
129
  simulateRequestScope(function () {
117
130
  const value = trackString('foo');
118
131
  const result = value.concat('bar');
119
132
  expect(tracker.getData(result)).to.be.null;
120
- }, {});
133
+ }, { assess: { policy: null } });
121
134
  });
122
135
 
123
136
  it('will not propagate if there instrumentation is locked', function () {
@@ -15,13 +15,14 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
18
19
  const { patchType } = require('../../common');
19
20
 
20
21
  module.exports = function(core) {
21
22
  const {
22
- scopes: { sources, instrumentation },
23
23
  patcher,
24
24
  assess: {
25
+ getSourceContext,
25
26
  eventFactory: { createPropagationEvent },
26
27
  dataflow: { tracker }
27
28
  }
@@ -35,9 +36,10 @@ module.exports = function(core) {
35
36
  patcher.patch(String.prototype, method, {
36
37
  name,
37
38
  patchType,
39
+ usePerf: true,
38
40
  post(data) {
39
41
  const { obj, result, hooked, orig } = data;
40
- if (!result || !sources.getStore()?.assess || instrumentation.isLocked()) return;
42
+ if (!result || !getSourceContext(PROPAGATOR)) return;
41
43
 
42
44
  const objInfo = tracker.getData(obj);
43
45
 
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string format-methods', function () {
8
8
  let core, trackString, simulateRequestScope, tracker;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -23,6 +24,18 @@ describe('assess dataflow propagation string format-methods', function () {
23
24
  sinon.resetHistory();
24
25
  });
25
26
 
27
+ // eslint-disable-next-line mocha/no-sibling-hooks
28
+ afterEach(function() {
29
+ core.Perf.fromAllToMap('patcher', allPatcher);
30
+ });
31
+
32
+ after(function() {
33
+ const stats = core.Perf.getStats(allPatcher);
34
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
35
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
36
+ }
37
+ });
38
+
26
39
  ['toLowerCase', 'toUpperCase', 'toLocaleLowerCase', 'toLocaleUpperCase'].forEach((method) => {
27
40
  it(method, function () {
28
41
  simulateRequestScope(function () {
@@ -41,12 +54,12 @@ describe('assess dataflow propagation string format-methods', function () {
41
54
  });
42
55
  });
43
56
 
44
- it('will not propagate if there is no assess context', function () {
57
+ it('will not propagate if there is no assess policy in request context', function () {
45
58
  simulateRequestScope(function () {
46
59
  const value = trackString('foo');
47
60
  const result = value.toLowerCase('bar');
48
61
  expect(tracker.getData(result)).to.be.null;
49
- }, {});
62
+ }, { assess: { policy: null } });
50
63
  });
51
64
 
52
65
  it('will not propagate if there instrumentation is locked', function () {
@@ -14,7 +14,6 @@
14
14
  */
15
15
 
16
16
  'use strict';
17
-
18
17
  const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
19
18
  const { createAppendTags } = require('../../../tag-utils');
20
19
  const { patchType } = require('../../common');
@@ -62,6 +61,7 @@ module.exports = function(core) {
62
61
  patcher.patch(String.prototype, 'anchor', {
63
62
  name,
64
63
  patchType,
64
+ usePost: true,
65
65
  post(data) {
66
66
  const { args, obj, result, hooked, orig } = data;
67
67
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string html-methods', function () {
8
8
  let core, trackString, simulateRequestScope, tracker;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -23,6 +24,18 @@ describe('assess dataflow propagation string html-methods', function () {
23
24
  sinon.resetHistory();
24
25
  });
25
26
 
27
+ // eslint-disable-next-line mocha/no-sibling-hooks
28
+ afterEach(function() {
29
+ core.Perf.fromAllToMap('patcher', allPatcher);
30
+ });
31
+
32
+ after(function() {
33
+ const stats = core.Perf.getStats(allPatcher);
34
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
35
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
36
+ }
37
+ });
38
+
26
39
  [
27
40
  {
28
41
  method: 'anchor',
@@ -144,12 +157,12 @@ describe('assess dataflow propagation string html-methods', function () {
144
157
  });
145
158
  });
146
159
 
147
- it('will not propagate if there is no assess context', function () {
160
+ it('will not propagate if there is no assess policy in request context', function () {
148
161
  simulateRequestScope(function () {
149
162
  const value = trackString('foo');
150
163
  const result = value.anchor('bar');
151
164
  expect(tracker.getData(result)).to.be.null;
152
- }, {});
165
+ }, { assess: { policy: null } });
153
166
  });
154
167
 
155
168
  it('will not propagate if there instrumentation is locked', function () {
@@ -15,8 +15,7 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const { callChildComponentMethodsSync } = require('@contrast/common');
19
- const { StringPrototypeSplit } = require('@contrast/common');
18
+ const { callChildComponentMethodsSync, primordials: { StringPrototypeSplit } } = require('@contrast/common');
20
19
  const { getAdjustedUntrackedValue } = require('../../../tag-utils');
21
20
 
22
21
  module.exports = function(core) {
@@ -46,6 +45,7 @@ module.exports = function(core) {
46
45
  return patcher.patch(matcherFn, {
47
46
  name,
48
47
  patchType,
48
+ usePerf: true,
49
49
  pre(data) {
50
50
  const { args: origArgs, hooked, orig } = data;
51
51
  if (
@@ -36,7 +36,7 @@ module.exports = function(core) {
36
36
  objInfo,
37
37
  startIdx,
38
38
  match,
39
- untrackedResult,
39
+ //untrackedResult,
40
40
  metadata,
41
41
  }) {
42
42
  const tags = createSubsetTags(objInfo.tags, startIdx, match.length);
@@ -75,6 +75,7 @@ module.exports = function(core) {
75
75
  patcher.patch(String.prototype, 'matchAll', {
76
76
  name,
77
77
  patchType,
78
+ usePerf: true,
78
79
  around(origFn, data) {
79
80
  const { args, obj, hooked, orig } = data;
80
81
 
@@ -17,6 +17,7 @@ function createItem(idx, itemValue = [''], input = 'foo', groups = undefined) {
17
17
 
18
18
  describe('assess dataflow propagation string matchAll', function () {
19
19
  let core, simulateRequestScope, trackString, tracker;
20
+ const allPatcher = new Map();
20
21
 
21
22
  beforeEach(function () {
22
23
  ({
@@ -38,6 +39,18 @@ describe('assess dataflow propagation string matchAll', function () {
38
39
  core.assess.dataflow.propagation.stringInstrumentation.substring.uninstall();
39
40
  });
40
41
 
42
+ // eslint-disable-next-line mocha/no-sibling-hooks
43
+ afterEach(function() {
44
+ core.Perf.fromAllToMap('patcher', allPatcher);
45
+ });
46
+
47
+ after(function() {
48
+ const stats = core.Perf.getStats(allPatcher);
49
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
50
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
51
+ }
52
+ });
53
+
41
54
  describe('base cases', function () {
42
55
  [
43
56
  [],
@@ -14,15 +14,18 @@
14
14
  */
15
15
 
16
16
  'use strict';
17
- const { ArrayPrototypeJoin } = require('@contrast/common');
18
- const { patchType } = require('../../common');
17
+
18
+ const { primordials: { ArrayPrototypeJoin } } = require('@contrast/common');
19
+ const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
19
20
  const { createSubsetTags, getAdjustedUntrackedValue } = require('../../../tag-utils');
21
+ const { patchType } = require('../../common');
20
22
 
21
23
  module.exports = function(core) {
22
24
  const {
23
- scopes: { sources, instrumentation },
25
+ scopes,
24
26
  patcher,
25
27
  assess: {
28
+ getSourceContext,
26
29
  eventFactory: { createPropagationEvent },
27
30
  dataflow: {
28
31
  tracker,
@@ -76,18 +79,16 @@ module.exports = function(core) {
76
79
  patcher.patch(String.prototype, 'match', {
77
80
  name,
78
81
  patchType,
82
+ usePerf: true,
79
83
  around(origFn, data) {
80
84
  const { args, obj } = data;
81
85
  if (
82
86
  !obj ||
83
87
  !args.length ||
84
- !sources.getStore()?.assess ||
85
88
  typeof obj !== 'string' ||
86
- instrumentation.isLocked() ||
87
- (args.length === 1 && !args[0])
88
- )
89
- return origFn();
90
-
89
+ (args.length === 1 && !args[0]) ||
90
+ !getSourceContext(PROPAGATOR)
91
+ ) return origFn();
91
92
  const objInfo = tracker.getData(obj);
92
93
 
93
94
  if (!objInfo) return origFn();
@@ -108,7 +109,7 @@ module.exports = function(core) {
108
109
  return origFn();
109
110
  }
110
111
 
111
- const result = (data.result = core.scopes.instrumentation.run(
112
+ const result = (data.result = scopes.instrumentation.run(
112
113
  { lock: true },
113
114
  () => origFn()
114
115
  ));
@@ -7,6 +7,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
7
7
 
8
8
  describe('assess dataflow propagation string match', function () {
9
9
  let core, simulateRequestScope, trackString, tracker;
10
+ const allPatcher = new Map();
10
11
 
11
12
  beforeEach(function () {
12
13
  ({
@@ -28,6 +29,18 @@ describe('assess dataflow propagation string match', function () {
28
29
  core.assess.dataflow.propagation.stringInstrumentation.substring.uninstall();
29
30
  });
30
31
 
32
+ // eslint-disable-next-line mocha/no-sibling-hooks
33
+ afterEach(function() {
34
+ core.Perf.fromAllToMap('patcher', allPatcher);
35
+ });
36
+
37
+ after(function() {
38
+ const stats = core.Perf.getStats(allPatcher);
39
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
40
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
41
+ }
42
+ });
43
+
31
44
  describe('base cases', function () {
32
45
  [
33
46
  [],
@@ -17,9 +17,13 @@
17
17
 
18
18
  const {
19
19
  DataflowTag: { UNTRUSTED },
20
- StringPrototypeMatch,
21
- ArrayPrototypeJoin,
22
- StringPrototypeSubstring,
20
+ primordials: {
21
+ StringPrototypeMatch,
22
+ ArrayPrototypeJoin,
23
+ ArrayPrototypeSlice,
24
+ StringPrototypeSubstring,
25
+ StringPrototypeReplace
26
+ }
23
27
  } = require('@contrast/common');
24
28
  const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
25
29
  const {
@@ -45,15 +49,16 @@ module.exports = function(core) {
45
49
  const len = args.length;
46
50
  const lastEl = args[len - 1];
47
51
  const hasNamedGroup = typeof lastEl === 'object';
48
- const captureGroups = args.slice(1, hasNamedGroup ? -3 : -2);
52
+ const captureGroups = ArrayPrototypeSlice.call(args, 1, hasNamedGroup ? -3 : -2);
49
53
  const matchIdx = args[hasNamedGroup ? len - 3 : len - 2];
50
54
  const str = hasNamedGroup ? args[len - 2] : lastEl;
51
55
  const namedGroups = hasNamedGroup ? lastEl : null;
52
56
  return { match, captureGroups, matchIdx, str, namedGroups };
53
57
  }
54
58
 
59
+ // these functions specifically use the patched versions of Substring so that
60
+ // the tags are propagated.
55
61
  function replaceSpecialCharacters(replacement, { captureGroups, match, str, namedGroups }, replacementType) {
56
- const origReplace = patcher.unwrap(String.prototype.replace);
57
62
  let ret = replacement;
58
63
  [
59
64
  {
@@ -79,22 +84,22 @@ module.exports = function(core) {
79
84
  if (tracker.getData(replace)) {
80
85
  ret = ret.replace(regex, replace);
81
86
  } else {
82
- ret = origReplace.call(ret, regex, replace);
87
+ ret = StringPrototypeReplace.call(ret, regex, replace);
83
88
  }
84
89
  }
85
90
  });
86
91
 
87
- const numberedGroupMatches = replacementType !== 'function' && replacement.match(/\$[1-9][0-9]|\$[1-9]/g);
92
+ const numberedGroupMatches = replacementType !== 'function' && StringPrototypeMatch.call(replacement, /\$[1-9][0-9]|\$[1-9]/g);
88
93
  if (numberedGroupMatches) {
89
94
  numberedGroupMatches.forEach((numberedGroup) => {
90
95
  const group = Number(StringPrototypeSubstring.call(numberedGroup, 1));
91
- ret = origReplace.call(ret, numberedGroup, captureGroups[group - 1] || '');
96
+ ret = StringPrototypeReplace.call(ret, numberedGroup, captureGroups[group - 1] || '');
92
97
  });
93
98
  }
94
99
 
95
100
  if (namedGroups) {
96
101
  for (const name in namedGroups) {
97
- ret = origReplace.call(ret, `$${name}`, namedGroups[name]);
102
+ ret = StringPrototypeReplace.call(ret, `$${name}`, namedGroups[name]);
98
103
  }
99
104
  }
100
105
 
@@ -145,6 +150,7 @@ module.exports = function(core) {
145
150
  patcher.patch(String.prototype, 'replace', {
146
151
  name,
147
152
  patchType,
153
+ usePerf: true,
148
154
  pre(data) {
149
155
  if (!getSourceContext(PROPAGATOR)) return;
150
156
 
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string replace', function () {
8
8
  let core, simulateRequestScope, trackString, tracker;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -24,6 +25,18 @@ describe('assess dataflow propagation string replace', function () {
24
25
  core.assess.dataflow.propagation.stringInstrumentation.replace.uninstall();
25
26
  });
26
27
 
28
+ // eslint-disable-next-line mocha/no-sibling-hooks
29
+ afterEach(function() {
30
+ core.Perf.fromAllToMap('patcher', allPatcher);
31
+ });
32
+
33
+ after(function() {
34
+ const stats = core.Perf.getStats(allPatcher);
35
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
36
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
37
+ }
38
+ });
39
+
27
40
  ['string', 'function'].forEach((replacerType) => {
28
41
  function getReplacement(replacerType, replacement) {
29
42
  return replacerType === 'function' ? () => replacement : replacement;
@@ -13,7 +13,7 @@
13
13
  * way not consistent with the End User License Agreement.
14
14
  */
15
15
  'use strict';
16
- const { ArrayPrototypeJoin } = require('@contrast/common');
16
+ const { primordials: { ArrayPrototypeJoin } } = require('@contrast/common');
17
17
  const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
18
18
  const { createSubsetTags, getAdjustedUntrackedValue } = require('../../../tag-utils');
19
19
  const { patchType } = require('../../common');
@@ -54,6 +54,7 @@ module.exports = function(core) {
54
54
  patcher.patch(String.prototype, 'slice', {
55
55
  name,
56
56
  patchType,
57
+ usePerf: true,
57
58
  post(data) {
58
59
  const { name, args: origArgs, obj, result, hooked, orig } = data;
59
60
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string slice', function () {
8
8
  let core, tracker, trackString, simulateRequestScope;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -23,6 +24,18 @@ describe('assess dataflow propagation string slice', function () {
23
24
  sinon.resetHistory();
24
25
  });
25
26
 
27
+ // eslint-disable-next-line mocha/no-sibling-hooks
28
+ afterEach(function() {
29
+ core.Perf.fromAllToMap('patcher', allPatcher);
30
+ });
31
+
32
+ after(function() {
33
+ const stats = core.Perf.getStats(allPatcher);
34
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
35
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
36
+ }
37
+ });
38
+
26
39
  [
27
40
  {
28
41
  desc: 'not tracked',
@@ -15,7 +15,7 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const { ArrayPrototypeJoin } = require('@contrast/common');
18
+ const { primordials: { ArrayPrototypeJoin } } = require('@contrast/common');
19
19
  const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
20
20
  const { createSubsetTags, getAdjustedUntrackedValue } = require('../../../tag-utils');
21
21
  const { patchType } = require('../../common');
@@ -37,6 +37,7 @@ module.exports = function(core) {
37
37
  patcher.patch(String.prototype, 'split', {
38
38
  name,
39
39
  patchType,
40
+ usePerf: true,
40
41
  post(data) {
41
42
  const { name, args: origArgs, obj, result, hooked, orig } = data;
42
43
  if (
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string split', function () {
8
8
  let core, simulateRequestScope, trackString, tracker;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -27,6 +28,18 @@ describe('assess dataflow propagation string split', function () {
27
28
  core.assess.dataflow.propagation.stringInstrumentation.split.uninstall();
28
29
  });
29
30
 
31
+ // eslint-disable-next-line mocha/no-sibling-hooks
32
+ afterEach(function() {
33
+ core.Perf.fromAllToMap('patcher', allPatcher);
34
+ });
35
+
36
+ after(function() {
37
+ const stats = core.Perf.getStats(allPatcher);
38
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
39
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
40
+ }
41
+ });
42
+
30
43
  describe('base cases', function () {
31
44
  it('normal split on non-tracked string', function () {
32
45
  simulateRequestScope(() => {
@@ -15,7 +15,7 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const { ArrayPrototypeJoin } = require('@contrast/common');
18
+ const { primordials: { ArrayPrototypeJoin } } = require('@contrast/common');
19
19
  const { InstrumentationType: { PROPAGATOR } } = require('../../../../constants');
20
20
  const { createSubsetTags, getAdjustedUntrackedValue } = require('../../../tag-utils');
21
21
  const { patchType } = require('../../common');
@@ -62,6 +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
66
  post(data) {
66
67
  const { obj, args: origArgs, result, name, hooked, orig } = data;
67
68
  if (!result || !getSourceContext(PROPAGATOR)) return;
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string substring', function () {
8
8
  let core, tracker, trackString, simulateRequestScope;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -23,6 +24,18 @@ describe('assess dataflow propagation string substring', function () {
23
24
  sinon.resetHistory();
24
25
  });
25
26
 
27
+ // eslint-disable-next-line mocha/no-sibling-hooks
28
+ afterEach(function() {
29
+ core.Perf.fromAllToMap('patcher', allPatcher);
30
+ });
31
+
32
+ after(function() {
33
+ const stats = core.Perf.getStats(allPatcher);
34
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
35
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
36
+ }
37
+ });
38
+
26
39
  [
27
40
  {
28
41
  desc: 'below',
@@ -92,18 +92,21 @@ module.exports = function(core) {
92
92
  name: 'String.prototype.trim',
93
93
  patchType,
94
94
  post: createPostHook('trim'),
95
+ usePerf: true,
95
96
  });
96
97
 
97
98
  patcher.patch(String.prototype, 'trimStart', {
98
99
  name: 'String.prototype.trimStart',
99
100
  patchType,
100
- post: createPostHook('trimStart')
101
+ post: createPostHook('trimStart'),
102
+ usePerf: true,
101
103
  });
102
104
 
103
105
  patcher.patch(String.prototype, 'trimEnd', {
104
106
  name: 'String.prototype.trimEnd',
105
107
  patchType,
106
108
  post: createPostHook('trimEnd', 0),
109
+ usePerf: true,
107
110
  });
108
111
  },
109
112
  uninstall() {
@@ -6,6 +6,7 @@ const { initAssessFixture } = require('@contrast/test/fixtures');
6
6
 
7
7
  describe('assess dataflow propagation string trim', function () {
8
8
  let core, tracker, trackString, simulateRequestScope;
9
+ const allPatcher = new Map();
9
10
 
10
11
  beforeEach(function () {
11
12
  ({
@@ -23,6 +24,18 @@ describe('assess dataflow propagation string trim', function () {
23
24
  sinon.resetHistory();
24
25
  });
25
26
 
27
+ // eslint-disable-next-line mocha/no-sibling-hooks
28
+ afterEach(function() {
29
+ core.Perf.fromAllToMap('patcher', allPatcher);
30
+ });
31
+
32
+ after(function() {
33
+ const stats = core.Perf.getStats(allPatcher);
34
+ for (const [key, { n, totalMicros, mean }] of stats.entries()) {
35
+ console.log(key, n, totalMicros, 'nsec', mean, 'mean');
36
+ }
37
+ });
38
+
26
39
  [
27
40
  {
28
41
  str: 'not-tracked',