@contrast/agent 4.5.1 → 4.7.1

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 (209) hide show
  1. package/bin/VERSION +1 -1
  2. package/bin/linux/contrast-service +0 -0
  3. package/bin/mac/contrast-service +0 -0
  4. package/bin/windows/contrast-service.exe +0 -0
  5. package/lib/assess/membrane/deserialization-membrane.js +4 -5
  6. package/lib/assess/membrane/source-membrane.js +16 -33
  7. package/lib/assess/models/call-context.js +1 -1
  8. package/lib/assess/policy/propagators.json +19 -21
  9. package/lib/assess/policy/rules.json +7 -2
  10. package/lib/assess/policy/signatures.json +42 -0
  11. package/lib/assess/policy/util.js +2 -1
  12. package/lib/assess/propagators/JSON/parse.js +1 -1
  13. package/lib/assess/propagators/JSON/stringify.js +3 -3
  14. package/lib/assess/propagators/array-prototype-join.js +7 -8
  15. package/lib/assess/propagators/common.js +7 -5
  16. package/lib/assess/propagators/dustjs/escape-html.js +22 -0
  17. package/lib/assess/propagators/dustjs/escape-js.js +22 -0
  18. package/lib/assess/propagators/encode-uri/encode-uri-component.js +22 -0
  19. package/lib/assess/propagators/encode-uri/encode-uri.js +22 -0
  20. package/lib/assess/propagators/handlebars-escape-expresssion.js +1 -1
  21. package/lib/assess/propagators/index.js +0 -2
  22. package/lib/assess/propagators/joi/boolean.js +1 -1
  23. package/lib/assess/propagators/joi/expression.js +1 -1
  24. package/lib/assess/propagators/joi/number.js +1 -1
  25. package/lib/assess/propagators/joi/string-base.js +1 -1
  26. package/lib/assess/propagators/joi/string-schema.js +12 -13
  27. package/lib/assess/propagators/joi/values.js +37 -22
  28. package/lib/assess/propagators/manager.js +12 -10
  29. package/lib/assess/propagators/mongoose/helpers.js +20 -0
  30. package/lib/assess/propagators/mongoose/index.js +18 -0
  31. package/lib/assess/propagators/mongoose/map.js +74 -0
  32. package/lib/assess/propagators/mongoose/string.js +104 -0
  33. package/lib/assess/propagators/mustache/escape.js +22 -0
  34. package/lib/assess/propagators/number.js +54 -0
  35. package/lib/assess/propagators/object.js +6 -7
  36. package/lib/assess/propagators/path/basename.js +14 -13
  37. package/lib/assess/propagators/path/common.js +156 -47
  38. package/lib/assess/propagators/path/dirname.js +14 -13
  39. package/lib/assess/propagators/path/extname.js +14 -13
  40. package/lib/assess/propagators/path/join.js +5 -1
  41. package/lib/assess/propagators/path/normalize.js +1 -2
  42. package/lib/assess/propagators/path/parse.js +1 -1
  43. package/lib/assess/propagators/path/relative.js +7 -5
  44. package/lib/assess/propagators/path/resolve.js +11 -2
  45. package/lib/assess/propagators/querystring/escape.js +20 -18
  46. package/lib/assess/propagators/querystring/parse.js +7 -5
  47. package/lib/assess/propagators/querystring/stringify.js +25 -24
  48. package/lib/assess/propagators/querystring/unescape.js +20 -18
  49. package/lib/assess/propagators/sequelize/sql-string-escape.js +1 -1
  50. package/lib/assess/propagators/sequelize/sql-string-format-named-parameters.js +1 -1
  51. package/lib/assess/propagators/sequelize/sql-string-format.js +3 -3
  52. package/lib/assess/propagators/sequelize/utils.js +2 -2
  53. package/lib/assess/propagators/string-prototype-replace.js +30 -28
  54. package/lib/assess/propagators/string-prototype-split.js +36 -36
  55. package/lib/assess/propagators/string-prototype-trim.js +15 -17
  56. package/lib/assess/propagators/string.js +12 -16
  57. package/lib/assess/propagators/template-escape.js +87 -0
  58. package/lib/assess/propagators/templates.js +10 -11
  59. package/lib/assess/propagators/url/url-prototype-parse.js +5 -6
  60. package/lib/assess/propagators/url/url-url.js +51 -43
  61. package/lib/assess/propagators/util/format.js +1 -1
  62. package/lib/assess/propagators/v8/init-hooks.js +3 -3
  63. package/lib/assess/propagators/validator/init-hooks.js +22 -22
  64. package/lib/assess/sinks/common.js +10 -5
  65. package/lib/assess/sinks/dustjs-linkedin-xss.js +131 -0
  66. package/lib/assess/sinks/libxmljs-xxe.js +1 -1
  67. package/lib/assess/sinks/mongodb.js +2 -1
  68. package/lib/assess/sinks/ssrf-url.js +1 -1
  69. package/lib/constants.js +4 -1
  70. package/lib/core/arch-components/dynamodb.js +1 -2
  71. package/lib/core/arch-components/dynamodbv3.js +44 -0
  72. package/lib/core/arch-components/index.js +1 -0
  73. package/lib/core/arch-components/rethinkdb.js +53 -0
  74. package/lib/core/config/options.js +3 -2
  75. package/lib/core/rewrite/injections.js +8 -0
  76. package/lib/core/stacktrace.js +2 -1
  77. package/lib/feature-set.js +1 -1
  78. package/lib/hooks/frameworks/base.js +8 -2
  79. package/lib/hooks/frameworks/http.js +23 -16
  80. package/lib/hooks/frameworks/http2.js +73 -0
  81. package/lib/hooks/frameworks/index.js +8 -3
  82. package/lib/hooks/http.js +112 -128
  83. package/lib/hooks/object-to-primitive.js +6 -7
  84. package/lib/hooks/patcher.js +75 -44
  85. package/lib/hooks/require.js +16 -22
  86. package/lib/instrumentation.js +0 -3
  87. package/lib/protect/rules/nosqli/nosql-injection-rule.js +228 -0
  88. package/lib/protect/rules/rule-factory.js +2 -2
  89. package/lib/protect/service.js +23 -11
  90. package/lib/protect/sinks/mongodb.js +56 -55
  91. package/lib/reporter/translations/to-protobuf/dtm/index.js +1 -1
  92. package/lib/reporter/translations/to-protobuf/dtm/ip-denylist-details.js +1 -1
  93. package/lib/reporter/translations/to-protobuf/dtm/rasp-rule-sample.js +1 -1
  94. package/lib/reporter/translations/to-protobuf/settings/defend-features.js +8 -6
  95. package/lib/reporter/translations/to-protobuf/settings/exclusions.js +5 -4
  96. package/lib/tracker.js +13 -65
  97. package/lib/util/some.js +27 -0
  98. package/lib/util/source-map.js +1 -1
  99. package/package.json +15 -16
  100. package/lib/hooks/frameworks/https.js +0 -42
  101. package/lib/protect/rules/nosqli/no-sql-injection-rule.js +0 -109
  102. package/node_modules/bindings/LICENSE.md +0 -22
  103. package/node_modules/bindings/README.md +0 -98
  104. package/node_modules/bindings/bindings.js +0 -221
  105. package/node_modules/bindings/package.json +0 -32
  106. package/node_modules/file-uri-to-path/.npmignore +0 -1
  107. package/node_modules/file-uri-to-path/.travis.yml +0 -30
  108. package/node_modules/file-uri-to-path/History.md +0 -21
  109. package/node_modules/file-uri-to-path/LICENSE +0 -20
  110. package/node_modules/file-uri-to-path/README.md +0 -74
  111. package/node_modules/file-uri-to-path/index.d.ts +0 -2
  112. package/node_modules/file-uri-to-path/index.js +0 -66
  113. package/node_modules/file-uri-to-path/package.json +0 -36
  114. package/node_modules/file-uri-to-path/test/test.js +0 -24
  115. package/node_modules/file-uri-to-path/test/tests.json +0 -13
  116. package/node_modules/glossy/LICENSE +0 -19
  117. package/node_modules/glossy/README.md +0 -129
  118. package/node_modules/glossy/index.js +0 -12
  119. package/node_modules/glossy/lib/glossy/parse.js +0 -520
  120. package/node_modules/glossy/lib/glossy/produce.js +0 -459
  121. package/node_modules/glossy/package.json +0 -47
  122. package/node_modules/glossy/test/decide.js +0 -7
  123. package/node_modules/glossy/test/decode_pri.js +0 -24
  124. package/node_modules/glossy/test/parse_3164.js +0 -104
  125. package/node_modules/glossy/test/parse_5424.js +0 -106
  126. package/node_modules/glossy/test/parse_5848.js +0 -40
  127. package/node_modules/glossy/test/parse_8601.js +0 -14
  128. package/node_modules/glossy/test/parse_rfc3339.js +0 -9
  129. package/node_modules/glossy/test/produce.js +0 -162
  130. package/node_modules/glossy/test/runner.js +0 -40
  131. package/node_modules/glossy/test/structure_data.js +0 -24
  132. package/node_modules/nan/CHANGELOG.md +0 -537
  133. package/node_modules/nan/LICENSE.md +0 -13
  134. package/node_modules/nan/README.md +0 -455
  135. package/node_modules/nan/doc/asyncworker.md +0 -146
  136. package/node_modules/nan/doc/buffers.md +0 -54
  137. package/node_modules/nan/doc/callback.md +0 -76
  138. package/node_modules/nan/doc/converters.md +0 -41
  139. package/node_modules/nan/doc/errors.md +0 -226
  140. package/node_modules/nan/doc/json.md +0 -62
  141. package/node_modules/nan/doc/maybe_types.md +0 -583
  142. package/node_modules/nan/doc/methods.md +0 -664
  143. package/node_modules/nan/doc/new.md +0 -147
  144. package/node_modules/nan/doc/node_misc.md +0 -123
  145. package/node_modules/nan/doc/object_wrappers.md +0 -263
  146. package/node_modules/nan/doc/persistent.md +0 -296
  147. package/node_modules/nan/doc/scopes.md +0 -73
  148. package/node_modules/nan/doc/script.md +0 -38
  149. package/node_modules/nan/doc/string_bytes.md +0 -62
  150. package/node_modules/nan/doc/v8_internals.md +0 -199
  151. package/node_modules/nan/doc/v8_misc.md +0 -85
  152. package/node_modules/nan/include_dirs.js +0 -1
  153. package/node_modules/nan/nan.h +0 -2898
  154. package/node_modules/nan/nan_callbacks.h +0 -88
  155. package/node_modules/nan/nan_callbacks_12_inl.h +0 -514
  156. package/node_modules/nan/nan_callbacks_pre_12_inl.h +0 -520
  157. package/node_modules/nan/nan_converters.h +0 -72
  158. package/node_modules/nan/nan_converters_43_inl.h +0 -68
  159. package/node_modules/nan/nan_converters_pre_43_inl.h +0 -42
  160. package/node_modules/nan/nan_define_own_property_helper.h +0 -29
  161. package/node_modules/nan/nan_implementation_12_inl.h +0 -430
  162. package/node_modules/nan/nan_implementation_pre_12_inl.h +0 -263
  163. package/node_modules/nan/nan_json.h +0 -166
  164. package/node_modules/nan/nan_maybe_43_inl.h +0 -356
  165. package/node_modules/nan/nan_maybe_pre_43_inl.h +0 -268
  166. package/node_modules/nan/nan_new.h +0 -340
  167. package/node_modules/nan/nan_object_wrap.h +0 -156
  168. package/node_modules/nan/nan_persistent_12_inl.h +0 -132
  169. package/node_modules/nan/nan_persistent_pre_12_inl.h +0 -242
  170. package/node_modules/nan/nan_private.h +0 -73
  171. package/node_modules/nan/nan_string_bytes.h +0 -305
  172. package/node_modules/nan/nan_typedarray_contents.h +0 -96
  173. package/node_modules/nan/nan_weak.h +0 -437
  174. package/node_modules/nan/package.json +0 -41
  175. package/node_modules/nan/tools/1to2.js +0 -412
  176. package/node_modules/nan/tools/README.md +0 -14
  177. package/node_modules/nan/tools/package.json +0 -19
  178. package/node_modules/unix-dgram/LICENSE +0 -13
  179. package/node_modules/unix-dgram/README.md +0 -107
  180. package/node_modules/unix-dgram/binding.gyp +0 -20
  181. package/node_modules/unix-dgram/build/Makefile +0 -324
  182. package/node_modules/unix-dgram/build/Release/.deps/Release/obj.target/unix_dgram/src/unix_dgram.o.d +0 -58
  183. package/node_modules/unix-dgram/build/Release/.deps/Release/obj.target/unix_dgram.node.d +0 -1
  184. package/node_modules/unix-dgram/build/Release/.deps/Release/unix_dgram.node.d +0 -1
  185. package/node_modules/unix-dgram/build/Release/obj.target/unix_dgram/src/unix_dgram.o +0 -0
  186. package/node_modules/unix-dgram/build/Release/obj.target/unix_dgram.node +0 -0
  187. package/node_modules/unix-dgram/build/Release/unix_dgram.node +0 -0
  188. package/node_modules/unix-dgram/build/binding.Makefile +0 -6
  189. package/node_modules/unix-dgram/build/config.gypi +0 -213
  190. package/node_modules/unix-dgram/build/unix_dgram.target.mk +0 -159
  191. package/node_modules/unix-dgram/lib/unix_dgram.js +0 -168
  192. package/node_modules/unix-dgram/package.json +0 -36
  193. package/node_modules/unix-dgram/src/unix_dgram.cc +0 -404
  194. package/node_modules/unix-dgram/src/win_dummy.cc +0 -7
  195. package/node_modules/unix-dgram/test/test-connect-callback.js +0 -68
  196. package/node_modules/unix-dgram/test/test-connect.js +0 -53
  197. package/node_modules/unix-dgram/test/test-dgram-unix.js +0 -58
  198. package/node_modules/unix-dgram/test/test-send-error.js +0 -26
  199. package/node_modules/winston-syslog/.eslintrc +0 -7
  200. package/node_modules/winston-syslog/.travis.yml +0 -14
  201. package/node_modules/winston-syslog/CHANGELOG.md +0 -9
  202. package/node_modules/winston-syslog/LICENSE +0 -20
  203. package/node_modules/winston-syslog/README.md +0 -135
  204. package/node_modules/winston-syslog/lib/utils.js +0 -26
  205. package/node_modules/winston-syslog/lib/winston-syslog.js +0 -385
  206. package/node_modules/winston-syslog/package.json +0 -56
  207. package/node_modules/winston-syslog/test/format-test.js +0 -122
  208. package/node_modules/winston-syslog/test/syslog-test.js +0 -95
  209. package/node_modules/winston-syslog/test/unix-connect-test.js +0 -133
@@ -20,14 +20,15 @@ const qsUtils = require('./utils');
20
20
 
21
21
  function handler(data) {
22
22
  const input = data.args[0];
23
+ const trackedData = tracker.getData(input);
23
24
 
24
- if (!input || !tracker.getData(input).tracked) {
25
+ if (!input || !trackedData) {
25
26
  return;
26
27
  }
27
28
 
28
29
  // adjust tag ranges
29
30
  const tagRanges = [];
30
- tracker.getData(input).tagRanges.forEach((tag) => {
31
+ trackedData.tagRanges.forEach((tag) => {
31
32
  if (tag.tag === 'url-encoded') {
32
33
  return;
33
34
  }
@@ -37,22 +38,23 @@ function handler(data) {
37
38
  return;
38
39
  }
39
40
 
40
- const trackedResult = tracker.track(data.result);
41
- const trackData = tracker.getData(trackedResult);
42
- trackData.tagRanges = tagRanges;
43
- trackData.event = new PropagationEvent({
44
- context: new CallContext({
45
- ...data,
46
- obj: null
47
- }),
48
- parents: [trackData.event],
49
- signature: new Signature('querystring.unescape'),
50
- source: 'P',
51
- tagRanges,
52
- target: 'R',
53
- untags: ['url-encoded']
54
- });
55
- data.result = trackedResult;
41
+ const tracked = tracker.track(data.result);
42
+ if (tracked) {
43
+ tracked.props.tagRanges = tagRanges;
44
+ tracked.props.event = new PropagationEvent({
45
+ context: new CallContext({
46
+ ...data,
47
+ obj: null
48
+ }),
49
+ parents: [tracked.props.event],
50
+ signature: new Signature('querystring.unescape'),
51
+ source: 'P',
52
+ tagRanges,
53
+ target: 'R',
54
+ untags: ['url-encoded']
55
+ });
56
+ data.result = tracked.str;
57
+ }
56
58
  }
57
59
 
58
60
  module.exports.handle = handler;
@@ -35,7 +35,7 @@ module.exports.handle = function() {
35
35
  post(data) {
36
36
  const trackingData = tracker.getData(data.result);
37
37
 
38
- if (!trackingData.tracked) {
38
+ if (!trackingData) {
39
39
  return;
40
40
  }
41
41
 
@@ -80,7 +80,7 @@ module.exports.handle = function() {
80
80
  patchType: PATCH_TYPES.ASSESS_PROPAGATOR,
81
81
  post(data) {
82
82
  const trackingData = tracker.getData(data.result);
83
- if (!trackingData.tracked) {
83
+ if (!trackingData) {
84
84
  return;
85
85
  }
86
86
 
@@ -44,7 +44,7 @@ module.exports.handle = function() {
44
44
  post(data) {
45
45
  // else either the replacement value or a values in the array replacement is being tracked
46
46
  const trackingData = tracker.getData(data.result);
47
- if (!trackingData.tracked) {
47
+ if (!trackingData) {
48
48
  return;
49
49
  }
50
50
 
@@ -59,7 +59,7 @@ module.exports.handle = function() {
59
59
  const len = positions.length; // micro optomized since used multiple times
60
60
 
61
61
  for (let i = 0; i < len; i++) {
62
- const isTracked = tracker.getData(replacements[i]).tracked;
62
+ const props = tracker.getData(replacements[i]);
63
63
  // we don't need to run in a no instrumentation scope here since
64
64
  // patcher will do so automatically since we're in a post hook
65
65
  const escapedVal = getSequelizeString().escape(
@@ -69,7 +69,7 @@ module.exports.handle = function() {
69
69
  true // true is required to get format function behavior.
70
70
  );
71
71
 
72
- if (isTracked) {
72
+ if (props && props.tracked) {
73
73
  tagRangeUtil.addInPlace(
74
74
  trackingData.tagRanges,
75
75
  new TagRange(
@@ -22,8 +22,8 @@ const tracker = require('../../../tracker');
22
22
  */
23
23
  module.exports.isTracked = function isTracked(value) {
24
24
  return Array.isArray(value)
25
- ? value.some((v) => typeof v === 'string' && tracker.getData(v).tracked)
26
- : tracker.getData(value).tracked;
25
+ ? value.some((v) => typeof v === 'string' && tracker.getData(v))
26
+ : !!tracker.getData(value);
27
27
  };
28
28
 
29
29
  /**
@@ -115,13 +115,13 @@ function getTrackData(callContext) {
115
115
  };
116
116
 
117
117
  const objData = tracker.getData(callContext.obj);
118
- if (objData.tracked) {
118
+ if (objData) {
119
119
  trackData.objData = objData;
120
120
  trackData.resultTagRanges = objData.tagRanges.map((r) => r.clone());
121
121
  }
122
122
 
123
123
  const replacerData = tracker.getData(callContext.args[1]);
124
- if (replacerData.tracked) {
124
+ if (replacerData) {
125
125
  trackData.replacerData = replacerData;
126
126
  }
127
127
 
@@ -243,7 +243,7 @@ function getReplacementAndCaptureDynamicTags({ callContext, args }) {
243
243
  // Allow propagation within replacer function so we can track return value.
244
244
  _replacer = invokeReplacer({ callContext, args, replacer });
245
245
  const data = tracker.getData(_replacer);
246
- if (data.tracked) {
246
+ if (data) {
247
247
  trackData.dynamicTagRanges = data.tagRanges;
248
248
  trackData.dynamicEvents.add(data.event);
249
249
  } else {
@@ -297,7 +297,7 @@ function wrapOriginalReplacerArguments({ callContext, args }) {
297
297
  // Only wrap arguments that are used by replacer,
298
298
  for (let idx = 0; idx < replacer.length; idx++) {
299
299
  // and only track if needed
300
- if (tracker.getData(args[idx]).tracked) {
300
+ if (tracker.getData(args[idx])) {
301
301
  continue;
302
302
  }
303
303
  trackReplacerArgAtPath({
@@ -330,20 +330,21 @@ function trackReplacerArgAtPath({ callContext, target, path, tagRanges }) {
330
330
  continue;
331
331
  }
332
332
 
333
- const result = tracker.track(_result);
334
- const trackData = tracker.getData(result);
335
- // TODO: Improve accuracy here by deriving actual ranges from source,
336
- // rather than applying "blanket" ranges the length of argument.
337
- const tagRange = new TagRange(0, result.length - 1, tag);
338
- trackData.tagRanges.push(tagRange);
339
- trackData.event = createPropagationEvent({
340
- callContext,
341
- tagRanges: [tagRange],
342
- result
343
- });
344
-
345
- captured.add(tag);
346
- target[path] = result;
333
+ const tracked = tracker.track(_result);
334
+ if (tracked) {
335
+ // TODO: Improve accuracy here by deriving actual ranges from source,
336
+ // rather than applying "blanket" ranges the length of argument.
337
+ const tagRange = new TagRange(0, tracked.str.length - 1, tag);
338
+ tracked.props.tagRanges.push(tagRange);
339
+ tracked.props.event = createPropagationEvent({
340
+ callContext,
341
+ tagRanges: [tagRange],
342
+ result: tracked.str
343
+ });
344
+
345
+ captured.add(tag);
346
+ target[path] = tracked.str;
347
+ }
347
348
  }
348
349
  } else if (_.isObject(_result)) {
349
350
  for (const path of Object.keys(_result)) {
@@ -582,20 +583,21 @@ function trackFinalResult(callContext) {
582
583
  return;
583
584
  }
584
585
 
585
- if (tracker.getData(callContext.result).tracked) {
586
+ if (tracker.getData(callContext.result)) {
586
587
  return;
587
588
  }
588
589
 
589
- const result = tracker.track(callContext.result);
590
- callContext.result = result;
590
+ const tracked = tracker.track(callContext.result);
591
591
 
592
- const resultData = tracker.getData(result);
593
- resultData.event = createPropagationEvent({
594
- callContext,
595
- tagRanges: trackData.resultTagRanges,
596
- result
597
- });
598
- resultData.tagRanges = trackData.resultTagRanges;
592
+ if (tracked) {
593
+ tracked.props.event = createPropagationEvent({
594
+ callContext,
595
+ tagRanges: trackData.resultTagRanges,
596
+ result: tracked.str
597
+ });
598
+ tracked.props.tagRanges = trackData.resultTagRanges;
599
+ callContext.result = tracked.str;
600
+ }
599
601
  }
600
602
 
601
603
  /**
@@ -164,28 +164,27 @@ module.exports.handle = {
164
164
  if (tagStart !== null) {
165
165
  newTagRanges.push(new TagRange(tagStart, tagStop, tag.tag));
166
166
  const tracked = tracker.track(stringPart);
167
- const props = tracker.getData(tracked);
168
- if (!props.tagRanges) {
169
- props.tagRanges = [];
167
+ if (tracked) {
168
+ tracked.props.tagRanges.push(new TagRange(tagStart, tagStop, tag.tag));
169
+ result[i] = tracked.str;
170
170
  }
171
- props.tagRanges.push(new TagRange(tagStart, tagStop, tag.tag));
172
- result[i] = tracked;
173
171
  }
174
172
  });
175
173
  if (newTagRanges.length > 0) {
176
174
  const tracked = tracker.track(stringPart);
177
- const props = tracker.getData(tracked);
178
- props.tagRanges = newTagRanges;
179
- result[i] = tracked;
180
- const event = new PropagationEvent({
181
- context: ctxt,
182
- signature: sig,
183
- tagRanges: tracked.tagRanges,
184
- source: 'O',
185
- target: 'R'
186
- });
187
- event.parents.push(oldEvent);
188
- props.event = event;
175
+ if (tracked) {
176
+ tracked.props.tagRanges = newTagRanges;
177
+ result[i] = tracked.str;
178
+ const event = new PropagationEvent({
179
+ context: ctxt,
180
+ signature: sig,
181
+ tagRanges: tracked.props.tagRanges,
182
+ source: 'O',
183
+ target: 'R'
184
+ });
185
+ event.parents.push(oldEvent);
186
+ tracked.props.event = event;
187
+ }
189
188
  }
190
189
  }
191
190
  data.result = result;
@@ -225,21 +224,21 @@ function handleEmptySeperator(data, oldTagRanges, oldEvent) {
225
224
  if (sharedCharInfo.has(i)) {
226
225
  info = sharedCharInfo.get(i);
227
226
  } else {
228
- const trackedString = tracker.track(char);
229
- const trackedProperties = tracker.getData(trackedString);
230
-
231
- const event = new PropagationEvent({
232
- context: ctxt,
233
- signature: sig,
234
- tagRanges: getTagRanges(trackedString),
235
- source: 'O',
236
- target: 'R'
237
- });
238
-
239
- trackedProperties.event = event;
240
- info = { event, tagRanges: trackedProperties.tagRanges };
241
- sharedCharInfo.set(i, info);
242
- result[i] = trackedString;
227
+ const tracked = tracker.track(char);
228
+ if (tracked) {
229
+ const event = new PropagationEvent({
230
+ context: ctxt,
231
+ signature: sig,
232
+ tagRanges: getTagRanges(tracked.str),
233
+ source: 'O',
234
+ target: 'R'
235
+ });
236
+
237
+ tracked.props.event = event;
238
+ info = { event, tagRanges: tracked.props.tagRanges };
239
+ sharedCharInfo.set(i, info);
240
+ result[i] = tracked.str;
241
+ }
243
242
  }
244
243
 
245
244
  info.tagRanges.push(new TagRange(0, 0, tag.tag));
@@ -257,10 +256,11 @@ function transferTracking(origString, resultArray) {
257
256
 
258
257
  for (let i = 0; i < resultArray.length; i++) {
259
258
  const tracked = tracker.track(resultArray[i]);
260
- const trackedProperties = tracker.getData(tracked);
261
- trackedProperties.tagRanges = getTagRanges(origString);
262
- trackedProperties.event = getEvent(origString);
263
- resultArray[i] = tracked;
259
+ if (tracked) {
260
+ tracked.props.tagRanges = getTagRanges(origString);
261
+ tracked.props.event = getEvent(origString);
262
+ resultArray[i] = tracked.str;
263
+ }
264
264
  }
265
265
  return resultArray;
266
266
  }
@@ -25,7 +25,7 @@ const signature = new Signature('String.prototype.trim');
25
25
  function handle(data) {
26
26
  const { obj, result } = data;
27
27
  const sourceMetadata = tracker.getData(obj);
28
- if (!sourceMetadata.tracked) {
28
+ if (!sourceMetadata) {
29
29
  return;
30
30
  }
31
31
 
@@ -43,21 +43,19 @@ function handle(data) {
43
43
  }
44
44
 
45
45
  const tracked = tracker.track(result);
46
- const trackedData = tracker.getData(tracked);
47
- if (!trackedData.tracked) {
48
- return;
46
+ if (tracked) {
47
+ tracked.props.tagRanges = targetRanges;
48
+ const context = new CallContext(data);
49
+ const event = new PropagationEvent({
50
+ context,
51
+ signature,
52
+ tagRanges: targetRanges,
53
+ source: 'O',
54
+ target: 'R'
55
+ });
56
+ event.parents.push(sourceEvent);
57
+ tracked.props.event = event;
58
+
59
+ data.result = tracked.str;
49
60
  }
50
- trackedData.tagRanges = targetRanges;
51
- const context = new CallContext(data);
52
- const event = new PropagationEvent({
53
- context,
54
- signature,
55
- tagRanges: targetRanges,
56
- source: 'O',
57
- target: 'R'
58
- });
59
- event.parents.push(sourceEvent);
60
- trackedData.event = event;
61
-
62
- data.result = tracked;
63
61
  }
@@ -41,30 +41,26 @@ function handle() {
41
41
 
42
42
  // Checks if the string literal form of the new String object is tracked.
43
43
  // If so, we will want to copy the existing tag ranges below.
44
- if (data.obj && !argData.tracked) {
44
+ if (data.obj && !argData) {
45
45
  argData = tracker.getData(data.result.toString());
46
46
  }
47
47
 
48
- if (!arg || !argData.tracked) {
48
+ if (!arg || !argData) {
49
49
  return;
50
50
  }
51
51
 
52
- const newStr = tracker.track(data.result);
53
- const newStrData = tracker.getData(newStr);
52
+ const tracked = tracker.track(data.result);
53
+ if (tracked) {
54
+ // In a constructor context, data.obj is set to the new String object.
55
+ // When a new String object is instantiated we must copy the existing tag
56
+ // ranges from the string literal to the new String object.
57
+ if (data.obj) {
58
+ tracked.props.event = argData.event;
59
+ tracked.props.tagRanges = tracked.props.tagRanges.concat(argData.tagRanges);
60
+ }
54
61
 
55
- if (!newStrData.tracked) {
56
- return;
57
- }
58
-
59
- // In a constructor context, data.obj is set to the new String object.
60
- // When a new String object is instantiated we must copy the existing tag
61
- // ranges from the string literal to the new String object.
62
- if (data.obj) {
63
- newStrData.event = argData.event;
64
- newStrData.tagRanges = newStrData.tagRanges.concat(argData.tagRanges);
62
+ data.result = tracked.str;
65
63
  }
66
-
67
- data.result = newStr;
68
64
  }
69
65
  });
70
66
  }
@@ -0,0 +1,87 @@
1
+ /**
2
+ Copyright: 2021 Contrast Security, Inc
3
+ Contact: support@contrastsecurity.com
4
+ License: Commercial
5
+
6
+ NOTICE: This Software and the patented inventions embodied within may only be
7
+ used as part of Contrast Security’s commercial offerings. Even though it is
8
+ made available through public repositories, use of this Software is subject to
9
+ the applicable End User Licensing Agreement found at
10
+ https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
11
+ between Contrast Security and the End User. The Software may not be reverse
12
+ engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
+ way not consistent with the End User License Agreement.
14
+ */
15
+ 'use strict';
16
+
17
+ const tracker = require('../../tracker');
18
+ const TagRange = require('../models/tag-range');
19
+ const { CallContext, PropagationEvent, Signature } = require('../models');
20
+
21
+ function getEscapedTagRanges(input, result, start, stop, tag) {
22
+ const textArr = input.split('').slice(start, stop + 1);
23
+ const escapedArr = result.split('');
24
+ const overlap = textArr.filter((x) => {
25
+ if (escapedArr.includes(x)) {
26
+ return x;
27
+ }
28
+ });
29
+ if (overlap.length === 0) {
30
+ return [];
31
+ }
32
+ const newTagRanges = [];
33
+ let firstIndex = escapedArr.indexOf(overlap[0]);
34
+ let currIndex = firstIndex;
35
+ let nextIndex;
36
+ for (let i = 1; i < overlap.length; i++) {
37
+ nextIndex = escapedArr.indexOf(overlap[i], currIndex + 1);
38
+ if (nextIndex !== currIndex + 1) {
39
+ newTagRanges.push(new TagRange(firstIndex, currIndex, tag));
40
+ firstIndex = nextIndex;
41
+ }
42
+ if (i === overlap.length - 1) {
43
+ newTagRanges.push(new TagRange(firstIndex, nextIndex, tag));
44
+ }
45
+ currIndex = nextIndex;
46
+ }
47
+ return newTagRanges;
48
+ }
49
+
50
+ function propagator(data, tagName, signatureName) {
51
+ const input = data.args[0];
52
+
53
+ const trackedData = tracker.getData(input);
54
+
55
+ if (!input || !trackedData) {
56
+ return;
57
+ }
58
+
59
+ // adjust tag ranges
60
+ const tagRanges = [];
61
+ trackedData.tagRanges.forEach((range) => {
62
+ const { start, stop, tag } = range;
63
+ tagRanges.push(
64
+ ...getEscapedTagRanges(input, data.result, start, stop, tag)
65
+ );
66
+ });
67
+ tagRanges.push(new TagRange(0, data.result.length - 1, tagName));
68
+ const tracked = tracker.track(data.result);
69
+ if (tracked) {
70
+ tracked.props.tagRanges = tagRanges;
71
+ tracked.props.event = new PropagationEvent({
72
+ context: new CallContext({
73
+ ...data,
74
+ obj: null
75
+ }),
76
+ parents: [tracked.props.event],
77
+ signature: new Signature(signatureName),
78
+ source: 'P',
79
+ target: 'R',
80
+ tagRanges,
81
+ tags: tagName
82
+ });
83
+ data.result = tracked.str;
84
+ }
85
+ }
86
+
87
+ module.exports.propagate = propagator;
@@ -21,10 +21,9 @@ const tracker = require('../../tracker.js');
21
21
 
22
22
  const { PropagationEvent, Signature, CallContext } = require('../models');
23
23
  const { isString } = require('../../util/is-string');
24
+ const injections = require('../../core/rewrite/injections');
24
25
 
25
- const ContrastMethods = require('../../core/rewrite/injections').get(
26
- 'ContrastMethods'
27
- );
26
+ const ContrastMethods = injections.get('ContrastMethods');
28
27
 
29
28
  /**
30
29
  * In order to propagate through template literals, we leverage rewriting to
@@ -76,17 +75,17 @@ function __contrastTag(...args) {
76
75
  });
77
76
 
78
77
  if (tagRanges.length > 0) {
79
- result = tracker.track(result);
80
- const resultContrastProperties = tracker.getData(result);
81
- if (resultContrastProperties.tracked) {
78
+ const tracked = tracker.track(result);
79
+ if (tracked) {
82
80
  buildProperties(
83
- resultContrastProperties,
81
+ tracked.props,
84
82
  tagRanges,
85
83
  expressions,
86
- result,
84
+ tracked.str,
87
85
  strings,
88
86
  sourceEvents
89
87
  );
88
+ result = tracked.str;
90
89
  }
91
90
  }
92
91
 
@@ -144,18 +143,18 @@ function buildProperties(props, tagRanges, exps, result, strings, events) {
144
143
  */
145
144
  function moveTags(exp, sourceEvents, tagRanges, offset) {
146
145
  const contrastProperties = tracker.getData(exp);
147
- const tracked = contrastProperties.tracked || tagRanges.length > 0;
146
+ const tracked = contrastProperties || tagRanges.length > 0;
148
147
  if (!tracked) {
149
148
  return tagRanges;
150
149
  }
151
150
 
152
- const event = contrastProperties.tracked && contrastProperties.event;
151
+ const event = contrastProperties && contrastProperties.event;
153
152
  if (event) {
154
153
  sourceEvents.push(event);
155
154
  }
156
155
 
157
156
  let newTagRanges = [];
158
- if (contrastProperties.tracked) newTagRanges = contrastProperties.tagRanges;
157
+ if (contrastProperties) newTagRanges = contrastProperties.tagRanges;
159
158
 
160
159
  return tagRangeUtil.addAllWithOffset(tagRanges, newTagRanges, offset);
161
160
  }
@@ -45,7 +45,7 @@ function handle(data) {
45
45
  const address = data.args[0];
46
46
  const sourceMetadata = tracker.getData(address);
47
47
 
48
- if (!sourceMetadata.tracked) {
48
+ if (!sourceMetadata) {
49
49
  return;
50
50
  }
51
51
 
@@ -71,9 +71,8 @@ function propagate(sourceMetadata, address, data) {
71
71
 
72
72
  if (part && typeof part === 'string' && part !== '') {
73
73
  const tracked = tracker.track(part);
74
- const trackedData = tracker.getData(tracked);
75
74
 
76
- if (!trackedData.tracked) {
75
+ if (!tracked) {
77
76
  continue;
78
77
  }
79
78
 
@@ -105,10 +104,10 @@ function propagate(sourceMetadata, address, data) {
105
104
  );
106
105
  event.parents.push(sourceEvent);
107
106
 
108
- trackedData.tagRanges = targetTagRanges;
109
- trackedData.event = event;
107
+ tracked.props.tagRanges = targetTagRanges;
108
+ tracked.props.event = event;
110
109
 
111
- url[key] = tracked;
110
+ url[key] = tracked.str;
112
111
  }
113
112
  }
114
113
  }