@contrast/assess 1.1.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 (111) hide show
  1. package/coverage/lcov-report/base.css +224 -0
  2. package/coverage/lcov-report/block-navigation.js +87 -0
  3. package/coverage/lcov-report/favicon.png +0 -0
  4. package/coverage/lcov-report/index.html +266 -0
  5. package/coverage/lcov-report/lib/dataflow/common.js.html +154 -0
  6. package/coverage/lcov-report/lib/dataflow/event-factory.js.html +598 -0
  7. package/coverage/lcov-report/lib/dataflow/index.html +191 -0
  8. package/coverage/lcov-report/lib/dataflow/index.js.html +190 -0
  9. package/coverage/lcov-report/lib/dataflow/propagation/common.js.html +145 -0
  10. package/coverage/lcov-report/lib/dataflow/propagation/index.html +131 -0
  11. package/coverage/lcov-report/lib/dataflow/propagation/index.js.html +190 -0
  12. package/coverage/lcov-report/lib/dataflow/propagation/install/contrast-methods/index.html +131 -0
  13. package/coverage/lcov-report/lib/dataflow/propagation/install/contrast-methods/index.js.html +184 -0
  14. package/coverage/lcov-report/lib/dataflow/propagation/install/contrast-methods/plus.js.html +397 -0
  15. package/coverage/lcov-report/lib/dataflow/propagation/install/string/concat.js.html +478 -0
  16. package/coverage/lcov-report/lib/dataflow/propagation/install/string/index.html +176 -0
  17. package/coverage/lcov-report/lib/dataflow/propagation/install/string/index.js.html +202 -0
  18. package/coverage/lcov-report/lib/dataflow/propagation/install/string/replace.js.html +496 -0
  19. package/coverage/lcov-report/lib/dataflow/propagation/install/string/substring.js.html +415 -0
  20. package/coverage/lcov-report/lib/dataflow/propagation/install/string/trim.js.html +403 -0
  21. package/coverage/lcov-report/lib/dataflow/signatures.js.html +5923 -0
  22. package/coverage/lcov-report/lib/dataflow/sinks/common.js.html +145 -0
  23. package/coverage/lcov-report/lib/dataflow/sinks/index.html +131 -0
  24. package/coverage/lcov-report/lib/dataflow/sinks/index.js.html +211 -0
  25. package/coverage/lcov-report/lib/dataflow/sinks/install/fastify/index.html +146 -0
  26. package/coverage/lcov-report/lib/dataflow/sinks/install/fastify/index.js.html +172 -0
  27. package/coverage/lcov-report/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js.html +319 -0
  28. package/coverage/lcov-report/lib/dataflow/sinks/install/fastify/xss.js.html +721 -0
  29. package/coverage/lcov-report/lib/dataflow/sinks/install/http.js.html +340 -0
  30. package/coverage/lcov-report/lib/dataflow/sinks/install/index.html +116 -0
  31. package/coverage/lcov-report/lib/dataflow/sources/common.js.html +145 -0
  32. package/coverage/lcov-report/lib/dataflow/sources/index.html +131 -0
  33. package/coverage/lcov-report/lib/dataflow/sources/index.js.html +226 -0
  34. package/coverage/lcov-report/lib/dataflow/sources/install/fastify.js.html +379 -0
  35. package/coverage/lcov-report/lib/dataflow/sources/install/http.js.html +502 -0
  36. package/coverage/lcov-report/lib/dataflow/sources/install/index.html +146 -0
  37. package/coverage/lcov-report/lib/dataflow/sources/install/qs.js.html +322 -0
  38. package/coverage/lcov-report/lib/dataflow/tag-utils.js.html +418 -0
  39. package/coverage/lcov-report/lib/dataflow/tracker.js.html +466 -0
  40. package/coverage/lcov-report/lib/dataflow/utils/index.html +116 -0
  41. package/coverage/lcov-report/lib/dataflow/utils/is-vulnerable.js.html +424 -0
  42. package/coverage/lcov-report/lib/index.html +116 -0
  43. package/coverage/lcov-report/lib/index.js.html +193 -0
  44. package/coverage/lcov-report/prettify.css +1 -0
  45. package/coverage/lcov-report/prettify.js +2 -0
  46. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  47. package/coverage/lcov-report/sorter.js +196 -0
  48. package/coverage/lcov.info +4856 -0
  49. package/coverage/tmp/coverage-9548-1675168551025-0.json +1 -0
  50. package/coverage/tmp/coverage-9551-1675168550963-0.json +1 -0
  51. package/coverage/tmp/coverage-9552-1675168550969-0.json +1 -0
  52. package/coverage/tmp/coverage-9553-1675168550970-0.json +1 -0
  53. package/coverage/tmp/coverage-9554-1675168550962-0.json +1 -0
  54. package/coverage/tmp/coverage-9555-1675168550965-0.json +1 -0
  55. package/coverage/tmp/coverage-9556-1675168550964-0.json +1 -0
  56. package/coverage/tmp/coverage-9557-1675168550969-0.json +1 -0
  57. package/coverage/tmp/coverage-9558-1675168550964-0.json +1 -0
  58. package/coverage/tmp/coverage-9559-1675168550971-0.json +1 -0
  59. package/lib/dataflow/event-factory.js +256 -0
  60. package/lib/dataflow/index.js +35 -0
  61. package/lib/dataflow/propagation/common.js +26 -0
  62. package/lib/dataflow/propagation/index.js +50 -0
  63. package/lib/dataflow/propagation/install/array-prototype-join.js +125 -0
  64. package/lib/dataflow/propagation/install/contrast-methods/add.js +104 -0
  65. package/lib/dataflow/propagation/install/contrast-methods/index.js +34 -0
  66. package/lib/dataflow/propagation/install/contrast-methods/tag.js +102 -0
  67. package/lib/dataflow/propagation/install/decode-uri-component.js +88 -0
  68. package/lib/dataflow/propagation/install/ejs/escape-xml.js +89 -0
  69. package/lib/dataflow/propagation/install/ejs/index.js +30 -0
  70. package/lib/dataflow/propagation/install/encode-uri-component.js +87 -0
  71. package/lib/dataflow/propagation/install/escape-html.js +89 -0
  72. package/lib/dataflow/propagation/install/escape.js +89 -0
  73. package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +89 -0
  74. package/lib/dataflow/propagation/install/mysql-connection-escape.js +111 -0
  75. package/lib/dataflow/propagation/install/pug/index.js +64 -0
  76. package/lib/dataflow/propagation/install/pug-runtime-escape.js +89 -0
  77. package/lib/dataflow/propagation/install/sql-template-strings.js +103 -0
  78. package/lib/dataflow/propagation/install/string/concat.js +108 -0
  79. package/lib/dataflow/propagation/install/string/format-methods.js +83 -0
  80. package/lib/dataflow/propagation/install/string/html-methods.js +163 -0
  81. package/lib/dataflow/propagation/install/string/index.js +38 -0
  82. package/lib/dataflow/propagation/install/string/replace.js +197 -0
  83. package/lib/dataflow/propagation/install/string/substring.js +117 -0
  84. package/lib/dataflow/propagation/install/string/trim.js +115 -0
  85. package/lib/dataflow/propagation/install/unescape.js +90 -0
  86. package/lib/dataflow/propagation/install/url/domain-parsers.js +89 -0
  87. package/lib/dataflow/propagation/install/url/index.js +33 -0
  88. package/lib/dataflow/propagation/install/validator/hooks.js +172 -0
  89. package/lib/dataflow/propagation/install/validator/index.js +28 -0
  90. package/lib/dataflow/propagation/install/validator/methods.js +82 -0
  91. package/lib/dataflow/signatures.js +2022 -0
  92. package/lib/dataflow/sinks/common.js +20 -0
  93. package/lib/dataflow/sinks/index.js +44 -0
  94. package/lib/dataflow/sinks/install/fastify/index.js +30 -0
  95. package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js +107 -0
  96. package/lib/dataflow/sinks/install/http.js +119 -0
  97. package/lib/dataflow/sinks/install/postgres/index.js +129 -0
  98. package/lib/dataflow/sources/common.js +20 -0
  99. package/lib/dataflow/sources/handler.js +114 -0
  100. package/lib/dataflow/sources/index.js +35 -0
  101. package/lib/dataflow/sources/install/fastify/cookie.js +61 -0
  102. package/lib/dataflow/sources/install/fastify/fastify.js +89 -0
  103. package/lib/dataflow/sources/install/fastify/index.js +31 -0
  104. package/lib/dataflow/sources/install/http.js +181 -0
  105. package/lib/dataflow/sources/install/qs.js +88 -0
  106. package/lib/dataflow/tag-utils.js +122 -0
  107. package/lib/dataflow/tracker.js +127 -0
  108. package/lib/dataflow/utils/is-safe-content-type.js +30 -0
  109. package/lib/dataflow/utils/is-vulnerable.js +113 -0
  110. package/lib/index.js +36 -0
  111. package/package.json +21 -0
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ module.exports = {
19
+ patchType: 'assess-dataflow-sink'
20
+ };
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { callChildComponentMethodsSync, Event } = require('@contrast/common');
19
+ const { isVulnerable } = require('../utils/is-vulnerable');
20
+ const { isSafeContentType } = require('../utils/is-safe-content-type');
21
+
22
+ module.exports = function (core) {
23
+ const {
24
+ messages
25
+ } = core;
26
+
27
+ const sinks = core.assess.dataflow.sinks = {
28
+ isVulnerable,
29
+ isSafeContentType,
30
+ reportFindings(data) {
31
+ messages.emit(Event.ASSESS_DATAFLOW_FINDING, data);
32
+ },
33
+ };
34
+
35
+ require('./install/http')(core);
36
+ require('./install/postgres')(core);
37
+ require('./install/fastify')(core);
38
+
39
+ sinks.install = function() {
40
+ callChildComponentMethodsSync(core.assess.dataflow.sinks, 'install');
41
+ };
42
+
43
+ return sinks;
44
+ };
@@ -0,0 +1,30 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { callChildComponentMethodsSync } = require('@contrast/common');
19
+
20
+ module.exports = function(core) {
21
+ const fastify = core.assess.dataflow.sinks.fastify = {};
22
+
23
+ require('./unvalidated-redirect')(core);
24
+
25
+ fastify.install = function() {
26
+ callChildComponentMethodsSync(fastify, 'install');
27
+ };
28
+
29
+ return fastify;
30
+ };
@@ -0,0 +1,107 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { isString } = require('@contrast/common');
19
+ const { createModuleLabel } = require('../../../propagation/common');
20
+ const { patchType } = require('../../common');
21
+
22
+ module.exports = function (core) {
23
+ const {
24
+ depHooks,
25
+ patcher,
26
+ scopes: { sources },
27
+ assess: {
28
+ dataflow: {
29
+ tracker,
30
+ sinks: { isVulnerable, reportFindings },
31
+ eventFactory: { createSinkEvent },
32
+ },
33
+ },
34
+ } = core;
35
+ const unvalidatedRedirect =
36
+ (core.assess.dataflow.sinks.fastify.unvalidatedRedirect = {});
37
+
38
+ const safeTags = [
39
+ 'limited-chars',
40
+ 'url-encoded',
41
+ 'html-encoded',
42
+ 'custom-validated',
43
+ 'custom-encoded'
44
+ ];
45
+ const requiredTag = 'untrusted';
46
+
47
+ /**
48
+ * Patches `Reply.prototype.redirect` for
49
+ * `unvalidated-redirect` checking
50
+ *
51
+ * @param {Fastify.Reply} Reply outgoing response
52
+ */
53
+ const registerUnvalidatedRedirectHandler = (Reply, version) => {
54
+ patcher.patch(Reply.prototype, 'redirect', {
55
+ name: 'fastify.Reply.prototype.redirect',
56
+ patchType,
57
+ post(data) {
58
+ const assessStore = sources.getStore()?.assess;
59
+ if (!assessStore) return;
60
+
61
+ const [code] = data.args;
62
+ // url can be first or second argument
63
+ const url = typeof code === 'string' ? code : data.args[1];
64
+
65
+ if (!url || !isString(url)) return;
66
+
67
+ const strInfo = tracker.getData(url);
68
+ if (!strInfo) return;
69
+
70
+ if (isVulnerable(requiredTag, safeTags, strInfo.tags)) {
71
+ const event = createSinkEvent({
72
+ name: 'fastify.reply.redirect',
73
+ object: `[${createModuleLabel('fastify', version)}].Reply`,
74
+ history: [strInfo],
75
+ args: [{
76
+ value: strInfo.value,
77
+ isTracked: true
78
+ }],
79
+ result: {
80
+ value: url,
81
+ isTracked: true,
82
+ },
83
+ tags: strInfo.tags,
84
+ source: 'P0',
85
+ stacktraceOpts: {
86
+ constructorOpt: data.hooked,
87
+ },
88
+ });
89
+
90
+ reportFindings({
91
+ ruleId: 'unvalidated-redirect',
92
+ metadata: event,
93
+ });
94
+ }
95
+ },
96
+ });
97
+ };
98
+
99
+ unvalidatedRedirect.install = function () {
100
+ depHooks.resolve(
101
+ { name: 'fastify', file: 'lib/reply' },
102
+ registerUnvalidatedRedirectHandler
103
+ );
104
+ };
105
+
106
+ return unvalidatedRedirect;
107
+ };
@@ -0,0 +1,119 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { Rule } = require('@contrast/common');
19
+ const { createObjectLabel } = require('../../propagation/common');
20
+ const { patchType } = require('../common');
21
+
22
+ module.exports = function(core) {
23
+ const {
24
+ depHooks,
25
+ patcher,
26
+ scopes: { sources },
27
+ assess: {
28
+ dataflow: {
29
+ tracker,
30
+ sinks: { isVulnerable, reportFindings, isSafeContentType },
31
+ eventFactory: { createSinkEvent },
32
+ },
33
+ },
34
+ } = core;
35
+ const http = core.assess.dataflow.sinks.http = {};
36
+
37
+ const safeTags = [
38
+ 'alphanum-space-hyphen',
39
+ 'cookie',
40
+ 'header',
41
+ 'limited-chars',
42
+ 'html-encoded',
43
+ 'sql-encoded',
44
+ 'url-encoded',
45
+ 'weak-url-encoded',
46
+ 'custom-validated',
47
+ 'custom-encoded'
48
+ ];
49
+ const requiredTag = 'untrusted';
50
+
51
+ const preHook = (name) => (data) => {
52
+ const sourceContext = sources.getStore()?.assess;
53
+ if (!sourceContext) return;
54
+
55
+ const payload = data.args[0];
56
+ if (!payload) return;
57
+
58
+ const strInfo = tracker.getData(payload);
59
+ if (!strInfo) return;
60
+
61
+ const { contentType } = sourceContext.responseData;
62
+ if (contentType && isSafeContentType(contentType)) return;
63
+
64
+ if (isVulnerable(requiredTag, safeTags, strInfo.tags)) {
65
+ const event = createSinkEvent({
66
+ ruleId: Rule.REFLECTED_XSS,
67
+ name,
68
+ history: [strInfo],
69
+ object: {
70
+ isTracked: false,
71
+ value: createObjectLabel('http.ServerResponse')
72
+ },
73
+ args: [{
74
+ value: strInfo.value,
75
+ isTracked: true
76
+ }],
77
+ result: {
78
+ value: null,
79
+ isTracked: false,
80
+ },
81
+ tags: strInfo.tags,
82
+ source: 'P0',
83
+ stacktraceOpts: {
84
+ constructorOpt: data.hooked
85
+ }
86
+ });
87
+
88
+ if (event) {
89
+ reportFindings({
90
+ ruleId: 'reflected-xss',
91
+ metadata: event
92
+ });
93
+ }
94
+ }
95
+ };
96
+
97
+ http.install = function() {
98
+ depHooks.resolve({ name: 'http' }, (http) => {
99
+ {
100
+ const name = 'http.ServerResponse.prototype.write';
101
+ patcher.patch(http.ServerResponse.prototype, 'write', {
102
+ name,
103
+ patchType,
104
+ pre: preHook(name),
105
+ });
106
+ }
107
+ {
108
+ const name = 'http.ServerResponse.prototype.end';
109
+ patcher.patch(http.ServerResponse.prototype, 'end', {
110
+ name,
111
+ patchType,
112
+ pre: preHook(name),
113
+ });
114
+ }
115
+ });
116
+ };
117
+
118
+ return http;
119
+ };
@@ -0,0 +1,129 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { isString } = require('@contrast/common');
19
+ const { patchType } = require('../../common');
20
+ const util = require('util');
21
+
22
+ module.exports = function (core) {
23
+ const {
24
+ depHooks,
25
+ patcher,
26
+ scopes: { sources },
27
+ assess: {
28
+ dataflow: {
29
+ tracker,
30
+ sinks: { isVulnerable, reportFindings },
31
+ eventFactory: { createSinkEvent },
32
+ },
33
+ },
34
+ } = core;
35
+
36
+ const postgres = core.assess.dataflow.sinks.postgres = {};
37
+
38
+ const safeTags = [
39
+ 'sql-encoded',
40
+ 'limited-chars',
41
+ 'custom-validated',
42
+ 'custom-encoded',
43
+ ];
44
+ const requiredTag = 'untrusted';
45
+
46
+ const preHook = (methodSignature) => (data) => {
47
+ const assessStore = sources.getStore()?.assess;
48
+ if (!assessStore) return;
49
+
50
+ const query = data.args[0]?.text || data.args[0];
51
+ if (!query || !isString(query)) return;
52
+
53
+ const strInfo = tracker.getData(query);
54
+ if (!strInfo) return;
55
+
56
+ if (isVulnerable(requiredTag, safeTags, strInfo.tags)) {
57
+ const event = createSinkEvent({
58
+ name: methodSignature,
59
+ history: [strInfo],
60
+ args: [
61
+ {
62
+ value: util.inspect(data.args[0]),
63
+ isTracked: true,
64
+ },
65
+ ],
66
+ result: {
67
+ value: data.result,
68
+ isTracked: false,
69
+ },
70
+ tags: strInfo.tags,
71
+ source: 'P0',
72
+ stacktraceOpts: {
73
+ constructorOpt: data.hooked,
74
+ },
75
+ });
76
+
77
+ reportFindings({
78
+ ruleId: 'sql-injection',
79
+ metadata: event,
80
+ });
81
+ }
82
+ };
83
+
84
+ postgres.install = function () {
85
+ const pgClientQueryPatchName = 'pg.Client.prototype.query';
86
+ depHooks.resolve({ name: 'pg', file: 'lib/client.js' }, client => {
87
+ patcher.patch(client.prototype, 'query', {
88
+ name: pgClientQueryPatchName,
89
+ patchType,
90
+ pre: preHook('pg/lib/client.prototype.query'),
91
+ });
92
+ });
93
+
94
+ const pgNativeClientQueryPatchName = 'pg.native.Client.prototype.query';
95
+ depHooks.resolve({ name: 'pg', file: 'lib/native/client.js' }, (client) => {
96
+ patcher.patch(client.prototype, 'query', {
97
+ name: pgNativeClientQueryPatchName,
98
+ patchType,
99
+ pre: preHook('pg/lib/native/client.prototype.query'),
100
+ });
101
+ });
102
+
103
+ const pgClientPatchName = `${patchType}:${pgClientQueryPatchName}.query`;
104
+ const pgNativeClientPatchName = `${patchType}:${pgNativeClientQueryPatchName}.query`;
105
+ depHooks.resolve({ name: 'pg-pool' }, (pool) => {
106
+ const name = 'pg-pool.Pool.prototype.query';
107
+ patcher.patch(pool.prototype, 'query', {
108
+ name,
109
+ patchType,
110
+ pre: (data) => {
111
+ const funcKeys = patcher.hooks.get(
112
+ data.obj.Client?.prototype?.query
113
+ )?.funcKeys;
114
+
115
+ if (
116
+ funcKeys &&
117
+ (funcKeys.has(pgClientPatchName) || funcKeys.has(pgNativeClientPatchName))
118
+ ) {
119
+ return;
120
+ }
121
+
122
+ preHook(name)(data);
123
+ },
124
+ });
125
+ });
126
+ };
127
+
128
+ return postgres;
129
+ };
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ module.exports = {
19
+ patchType: 'assess-dataflow-source',
20
+ };
@@ -0,0 +1,114 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { isString, traverseValues } = require('@contrast/common');
19
+
20
+ module.exports = function(core) {
21
+ const {
22
+ assess: {
23
+ dataflow: {
24
+ sources,
25
+ tracker,
26
+ eventFactory: { createSourceEvent }
27
+ }
28
+ },
29
+ createSnapshot,
30
+ config,
31
+ logger,
32
+ } = core;
33
+
34
+ const emptyStack = Object.freeze([]);
35
+
36
+ sources.createTags = function createTags({ inputType, key, value }) {
37
+ if (!value?.length) {
38
+ return null;
39
+ }
40
+
41
+ const stop = value.length - 1;
42
+ const tags = {
43
+ untrusted: [0, stop]
44
+ };
45
+
46
+ if (inputType === 'header' && key.toLowerCase() === 'referer') {
47
+ tags.header = [0, stop];
48
+ }
49
+
50
+ if (inputType === 'cookie') {
51
+ tags.cookie = [0, stop];
52
+ }
53
+
54
+ return tags;
55
+ };
56
+
57
+ sources.handle = function({
58
+ name,
59
+ inputType = 'unknown',
60
+ stacktraceOpts,
61
+ data,
62
+ }) {
63
+ if (!data) return;
64
+
65
+ const max = config.assess.max_context_source_events;
66
+ const sourceContext = core.scopes.sources.getStore()?.assess;
67
+
68
+ if (!sourceContext) {
69
+ core.logger.trace({ inputType, name }, 'skipping assess source handling - no request context');
70
+ return null;
71
+ }
72
+
73
+ // todo: NODE-2789
74
+ const stack = config.assess.stacktraces === 'NONE'
75
+ ? emptyStack
76
+ : createSnapshot(stacktraceOpts)();
77
+
78
+ traverseValues(data, (path, type, value, obj) => {
79
+ if (sourceContext.sourceEventsCount >= max) {
80
+ core.logger.trace({ inputType, name }, 'exiting assess source handling - %s max events exceeded', max);
81
+ return true;
82
+ }
83
+
84
+ if (isString(value) && value.length) {
85
+ const key = path[path.length - 1];
86
+ const pathName = path.join('.');
87
+ const event = createSourceEvent({
88
+ name,
89
+ pathName,
90
+ stack,
91
+ inputType,
92
+ tags: sources.createTags({ inputType, key, value }),
93
+ result: { tracked: true, value },
94
+ });
95
+
96
+ if (!event) {
97
+ core.logger.warn({ inputType, name, pathName, value }, 'unable to create source event');
98
+ return;
99
+ }
100
+
101
+ const { extern } = tracker.track(value, event);
102
+ if (extern) {
103
+ logger.trace({ extern, key, inputType }, 'tracked');
104
+ obj[key] = extern;
105
+ sourceContext.sourceEventsCount++;
106
+ }
107
+ }
108
+ });
109
+
110
+ return data;
111
+ };
112
+
113
+ return sources;
114
+ };
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { callChildComponentMethodsSync } = require('@contrast/common');
19
+
20
+ module.exports = function(core) {
21
+ const sources = core.assess.dataflow.sources = {};
22
+
23
+ // API
24
+ require('./handler')(core);
25
+ // installers
26
+ require('./install/http')(core);
27
+ require('./install/fastify')(core);
28
+ require('./install/qs')(core);
29
+
30
+ sources.install = function install() {
31
+ callChildComponentMethodsSync(sources, 'install');
32
+ };
33
+
34
+ return sources;
35
+ };
@@ -0,0 +1,61 @@
1
+ /*
2
+ * Copyright: 2022 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
+
16
+ 'use strict';
17
+
18
+ const { InputType } = require('@contrast/common');
19
+ const { patchType } = require('../../common');
20
+
21
+ module.exports = function(core) {
22
+ const {
23
+ depHooks,
24
+ patcher,
25
+ assess: { dataflow: { sources } },
26
+ } = core;
27
+
28
+ const source = sources.fastifyInstrumentation.cookie = {
29
+ install() {
30
+ [
31
+ '@fastify/cookie',
32
+ 'fastify-cookie'
33
+ ].forEach((moduleName) => {
34
+ depHooks.resolve({ name: moduleName }, (lib) => patcher.patch(lib, {
35
+ name: `${moduleName}.constructor`,
36
+ patchType,
37
+ post({ args: [server] }) {
38
+ const name = 'fastifyServer.parseCookie';
39
+ patcher.patch(server, 'parseCookie', {
40
+ name,
41
+ patchType,
42
+ post({ hooked, orig, result: cookies }) {
43
+ sources.handle({
44
+ name,
45
+ inputType: InputType.COOKIE_VALUE,
46
+ stacktraceOpts: {
47
+ constructorOpt: hooked,
48
+ prependFrames: [orig]
49
+ },
50
+ data: cookies,
51
+ });
52
+ }
53
+ });
54
+ }
55
+ }));
56
+ });
57
+ }
58
+ };
59
+
60
+ return source;
61
+ };