@contrast/assess 1.30.0 → 1.32.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 (156) hide show
  1. package/lib/crypto-analysis/install/crypto.test.js +146 -0
  2. package/lib/crypto-analysis/install/math.test.js +65 -0
  3. package/lib/dataflow/index.test.js +36 -0
  4. package/lib/dataflow/propagation/index.test.js +103 -0
  5. package/lib/dataflow/propagation/install/JSON/index.test.js +50 -0
  6. package/lib/dataflow/propagation/install/JSON/parse-fn.test.js +232 -0
  7. package/lib/dataflow/propagation/install/JSON/parse.test.js +968 -0
  8. package/lib/dataflow/propagation/install/JSON/stringify.test.js +265 -0
  9. package/lib/dataflow/propagation/install/array-prototype-join.test.js +106 -0
  10. package/lib/dataflow/propagation/install/buffer.test.js +109 -0
  11. package/lib/dataflow/propagation/install/contrast-methods/add.test.js +94 -0
  12. package/lib/dataflow/propagation/install/contrast-methods/index.test.js +49 -0
  13. package/lib/dataflow/propagation/install/contrast-methods/number.test.js +50 -0
  14. package/lib/dataflow/propagation/install/contrast-methods/string.test.js +148 -0
  15. package/lib/dataflow/propagation/install/contrast-methods/tag.test.js +145 -0
  16. package/lib/dataflow/propagation/install/decode-uri-component.test.js +78 -0
  17. package/lib/dataflow/propagation/install/ejs/escape-xml.test.js +69 -0
  18. package/lib/dataflow/propagation/install/ejs/template.test.js +62 -0
  19. package/lib/dataflow/propagation/install/encode-uri.test.js +83 -0
  20. package/lib/dataflow/propagation/install/escape-html.test.js +71 -0
  21. package/lib/dataflow/propagation/install/escape.test.js +73 -0
  22. package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.test.js +71 -0
  23. package/lib/dataflow/propagation/install/isnumeric-0.test.js +58 -0
  24. package/lib/dataflow/propagation/install/joi/any.test.js +270 -0
  25. package/lib/dataflow/propagation/install/joi/array.test.js +912 -0
  26. package/lib/dataflow/propagation/install/joi/boolean.test.js +103 -0
  27. package/lib/dataflow/propagation/install/joi/expression.test.js +76 -0
  28. package/lib/dataflow/propagation/install/joi/index.test.js +39 -0
  29. package/lib/dataflow/propagation/install/joi/number.test.js +103 -0
  30. package/lib/dataflow/propagation/install/joi/object.test.js +119 -0
  31. package/lib/dataflow/propagation/install/joi/ref.test.js +607 -0
  32. package/lib/dataflow/propagation/install/joi/string-schema.test.js +513 -0
  33. package/lib/dataflow/propagation/install/mongoose/index.test.js +42 -0
  34. package/lib/dataflow/propagation/install/mongoose/schema-map.test.js +348 -0
  35. package/lib/dataflow/propagation/install/mongoose/schema-mixed.test.js +512 -0
  36. package/lib/dataflow/propagation/install/mongoose/schema-string.test.js +160 -0
  37. package/lib/dataflow/propagation/install/mustache-escape.test.js +62 -0
  38. package/lib/dataflow/propagation/install/mysql-connection-escape.test.js +74 -0
  39. package/lib/dataflow/propagation/install/parse-int.test.js +48 -0
  40. package/lib/dataflow/propagation/install/path/basename.test.js +143 -0
  41. package/lib/dataflow/propagation/install/path/dirname.test.js +167 -0
  42. package/lib/dataflow/propagation/install/path/extname.test.js +141 -0
  43. package/lib/dataflow/propagation/install/path/format.test.js +250 -0
  44. package/lib/dataflow/propagation/install/path/index.test.js +45 -0
  45. package/lib/dataflow/propagation/install/path/join-and-resolve.test.js +485 -0
  46. package/lib/dataflow/propagation/install/path/normalize.test.js +176 -0
  47. package/lib/dataflow/propagation/install/path/parse.test.js +238 -0
  48. package/lib/dataflow/propagation/install/path/relative.test.js +239 -0
  49. package/lib/dataflow/propagation/install/path/toNamespacedPath.test.js +158 -0
  50. package/lib/dataflow/propagation/install/pug/index.test.js +55 -0
  51. package/lib/dataflow/propagation/install/pug-runtime-escape.test.js +69 -0
  52. package/lib/dataflow/propagation/install/querystring/escape.test.js +63 -0
  53. package/lib/dataflow/propagation/install/querystring/index.test.js +40 -0
  54. package/lib/dataflow/propagation/install/querystring/parse.test.js +272 -0
  55. package/lib/dataflow/propagation/install/querystring/stringify.test.js +301 -0
  56. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.test.js +281 -0
  57. package/lib/dataflow/propagation/install/send.test.js +63 -0
  58. package/lib/dataflow/propagation/install/sequelize/query-generator.test.js +73 -0
  59. package/lib/dataflow/propagation/install/sequelize/sql-string.test.js +130 -0
  60. package/lib/dataflow/propagation/install/sql-template-strings.test.js +100 -0
  61. package/lib/dataflow/propagation/install/string/concat.test.js +132 -0
  62. package/lib/dataflow/propagation/install/string/format-methods.test.js +61 -0
  63. package/lib/dataflow/propagation/install/string/html-methods.test.js +164 -0
  64. package/lib/dataflow/propagation/install/string/index.test.js +103 -0
  65. package/lib/dataflow/propagation/install/string/match-all.test.js +399 -0
  66. package/lib/dataflow/propagation/install/string/match.test.js +361 -0
  67. package/lib/dataflow/propagation/install/string/replace.test.js +588 -0
  68. package/lib/dataflow/propagation/install/string/slice.test.js +265 -0
  69. package/lib/dataflow/propagation/install/string/split.test.js +500 -0
  70. package/lib/dataflow/propagation/install/string/substring.test.js +238 -0
  71. package/lib/dataflow/propagation/install/string/trim.test.js +122 -0
  72. package/lib/dataflow/propagation/install/unescape.test.js +78 -0
  73. package/lib/dataflow/propagation/install/url/domain-parsers.test.js +63 -0
  74. package/lib/dataflow/propagation/install/url/parse.test.js +391 -0
  75. package/lib/dataflow/propagation/install/url/searchParams.test.js +538 -0
  76. package/lib/dataflow/propagation/install/url/url.test.js +466 -0
  77. package/lib/dataflow/propagation/install/util-format.test.js +336 -0
  78. package/lib/dataflow/propagation/install/validator/hooks.test.js +211 -0
  79. package/lib/dataflow/sinks/index.test.js +78 -0
  80. package/lib/dataflow/sinks/install/child-process.test.js +338 -0
  81. package/lib/dataflow/sinks/install/eval.test.js +95 -0
  82. package/lib/dataflow/sinks/install/express/index.test.js +33 -0
  83. package/lib/dataflow/sinks/install/express/reflected-xss.js +55 -57
  84. package/lib/dataflow/sinks/install/express/reflected-xss.test.js +109 -0
  85. package/lib/dataflow/sinks/install/express/unvalidated-redirect.test.js +144 -0
  86. package/lib/dataflow/sinks/install/fastify/index.test.js +32 -0
  87. package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.test.js +130 -0
  88. package/lib/dataflow/sinks/install/fs.test.js +138 -0
  89. package/lib/dataflow/sinks/install/function.test.js +103 -0
  90. package/lib/dataflow/sinks/install/hapi/index.test.js +32 -0
  91. package/lib/dataflow/sinks/install/hapi/unvalidated-redirect.test.js +130 -0
  92. package/lib/dataflow/sinks/install/http/index.test.js +33 -0
  93. package/lib/dataflow/sinks/install/http/request.test.js +184 -0
  94. package/lib/dataflow/sinks/install/http/server-response.test.js +162 -0
  95. package/lib/dataflow/sinks/install/koa/index.test.js +32 -0
  96. package/lib/dataflow/sinks/install/koa/unvalidated-redirect.test.js +200 -0
  97. package/lib/dataflow/sinks/install/libxmljs.test.js +158 -0
  98. package/lib/dataflow/sinks/install/marsdb.test.js +166 -0
  99. package/lib/dataflow/sinks/install/mongodb.test.js +621 -0
  100. package/lib/dataflow/sinks/install/mssql.test.js +136 -0
  101. package/lib/dataflow/sinks/install/mysql.test.js +233 -0
  102. package/lib/dataflow/sinks/install/node-serialize.test.js +85 -0
  103. package/lib/dataflow/sinks/install/postgres.test.js +158 -0
  104. package/lib/dataflow/sinks/install/restify.test.js +142 -0
  105. package/lib/dataflow/sinks/install/sequelize.test.js +100 -0
  106. package/lib/dataflow/sinks/install/sqlite3.test.js +118 -0
  107. package/lib/dataflow/sinks/install/vm.test.js +326 -0
  108. package/lib/dataflow/sources/handler.test.js +463 -0
  109. package/lib/dataflow/sources/index.test.js +58 -0
  110. package/lib/dataflow/sources/install/body-parser1.test.js +248 -0
  111. package/lib/dataflow/sources/install/busboy.test.js +152 -0
  112. package/lib/dataflow/sources/install/cookie-parser1.test.js +143 -0
  113. package/lib/dataflow/sources/install/express/params.test.js +105 -0
  114. package/lib/dataflow/sources/install/express/parsedUrl.test.js +65 -0
  115. package/lib/dataflow/sources/install/fastify/fastify.js +1 -1
  116. package/lib/dataflow/sources/install/fastify/fastify.test.js +210 -0
  117. package/lib/dataflow/sources/install/fastify/index.test.js +33 -0
  118. package/lib/dataflow/sources/install/formidable1.test.js +119 -0
  119. package/lib/dataflow/sources/install/hapi/hapi.test.js +172 -0
  120. package/lib/dataflow/sources/install/hapi/index.test.js +33 -0
  121. package/lib/dataflow/sources/install/http.test.js +155 -0
  122. package/lib/dataflow/sources/install/koa/index.test.js +40 -0
  123. package/lib/dataflow/sources/install/koa/koa-bodyparsers.test.js +161 -0
  124. package/lib/dataflow/sources/install/koa/koa-multer.test.js +197 -0
  125. package/lib/dataflow/sources/install/koa/koa-routers.test.js +146 -0
  126. package/lib/dataflow/sources/install/koa/koa2.test.js +145 -0
  127. package/lib/dataflow/sources/install/multer1.test.js +145 -0
  128. package/lib/dataflow/sources/install/qs6.test.js +131 -0
  129. package/lib/dataflow/sources/install/querystring.test.js +82 -0
  130. package/lib/dataflow/sources/install/restify/fieldedTextBodyParser.test.js +88 -0
  131. package/lib/dataflow/sources/install/restify/index.test.js +38 -0
  132. package/lib/dataflow/sources/install/restify/jsonBodyParser.test.js +144 -0
  133. package/lib/dataflow/sources/install/restify/router.test.js +83 -0
  134. package/lib/dataflow/tag-utils-complete.test.js +27 -0
  135. package/lib/dataflow/tag-utils.test.js +192 -0
  136. package/lib/dataflow/tracker.test.js +216 -0
  137. package/lib/dataflow/utils/is-safe-content-type.test.js +16 -0
  138. package/lib/dataflow/utils/is-vulnerable.test.js +115 -0
  139. package/lib/event-factory.test.js +321 -0
  140. package/lib/get-policy.test.js +194 -0
  141. package/lib/get-source-context.test.js +108 -0
  142. package/lib/index.test.js +41 -0
  143. package/lib/make-source-context.test.js +50 -0
  144. package/lib/response-scanning/handlers/index.test.js +425 -0
  145. package/lib/response-scanning/handlers/utils.test.js +391 -0
  146. package/lib/response-scanning/index.test.js +41 -0
  147. package/lib/response-scanning/install/http.test.js +175 -0
  148. package/lib/rule-scopes.test.js +27 -0
  149. package/lib/session-configuration/handlers.test.js +84 -0
  150. package/lib/session-configuration/index.test.js +36 -0
  151. package/lib/session-configuration/install/express-session.test.js +220 -0
  152. package/lib/session-configuration/install/fastify-cookie.test.js +65 -0
  153. package/lib/session-configuration/install/hapi.test.js +269 -0
  154. package/lib/session-configuration/install/koa.js +50 -44
  155. package/lib/session-configuration/install/koa.test.js +92 -0
  156. package/package.json +2 -2
@@ -0,0 +1,146 @@
1
+ 'use strict';
2
+
3
+ const { expect } = require('chai');
4
+ const sinon = require('sinon');
5
+ const { Rule } = require('@contrast/common');
6
+ const { ConfigSource } = require('@contrast/config');
7
+ const { initAssessFixture } = require('@contrast/test/fixtures');
8
+
9
+ describe('assess crypto-analysis node:crypto', function () {
10
+ let core, simulateRequestScope, mockCrypto;
11
+
12
+ beforeEach(function () {
13
+ ({ core, simulateRequestScope } = initAssessFixture());
14
+ mockCrypto = {
15
+ createHash: sinon.stub(),
16
+ createCipher: sinon.stub(),
17
+ createCipheriv: sinon.stub(),
18
+ };
19
+ core.depHooks.resolve.withArgs({ name: 'crypto' }).yields(mockCrypto);
20
+ sinon.spy(core.assess.cryptoAnalysis, 'report');
21
+ core.assess.cryptoAnalysis.installers.crypto.install();
22
+ });
23
+
24
+ describe('crypto.createHash()', function() {
25
+ [
26
+ 'sha2-224',
27
+ 'Sha224',
28
+ 'rsa-sha256',
29
+ 'sha256withrsaencryption',
30
+ 'sha-384',
31
+ 'SHA384WITHRSAENCRYPTION',
32
+ 'sha-512',
33
+ 'sha2-512',
34
+ 'sha512',
35
+ 'ShA512WiThRsAeNcRyPtIoN',
36
+ ].forEach((alg) => {
37
+ it(`doesn't report when algorithm is safe: ${alg}`, function () {
38
+ simulateRequestScope(() => {
39
+ mockCrypto.createHash(alg);
40
+ expect(core.assess.cryptoAnalysis.report).not.to.have.been.called;
41
+ });
42
+ });
43
+ });
44
+
45
+ [
46
+ 'RSA-SHA1-2',
47
+ 'MD4',
48
+ 'md5',
49
+ 'MD5-SHA1',
50
+ ].forEach((alg) => {
51
+ it(`reports when algorithm is unsafe: ${alg}`, function () {
52
+ simulateRequestScope(() => {
53
+ mockCrypto.createHash(alg);
54
+ expect(core.assess.cryptoAnalysis.report).to.have.been.calledWithMatch({
55
+ ruleId: Rule.CRYPTO_BAD_MAC,
56
+ finding: sinon.match({
57
+ args: [{ tracked: false, value: alg }],
58
+ methodName: 'createHash',
59
+ moduleName: 'crypto',
60
+ object: { tracked: false, value: 'crypto' },
61
+ result: { tracked: false, value: 'Hash' },
62
+ source: 'P0',
63
+ stack: sinon.match.array,
64
+ stacktraceOpts: {
65
+ constructorOpt: sinon.match.func,
66
+ }
67
+ }),
68
+ });
69
+ });
70
+ });
71
+ });
72
+
73
+ [
74
+ 'etag',
75
+ 'browserify',
76
+ 'deps-sort'
77
+ ].forEach((lib) => {
78
+ [
79
+ 'ALL',
80
+ 'SOME'
81
+ ].forEach((stacktraceConfig) => {
82
+ it('will not report when library is trusted', function() {
83
+ core.config.setValue('assess.stacktraces', stacktraceConfig, ConfigSource.ENVIRONMENT_VARIABLE);
84
+ simulateRequestScope(() => {
85
+ sinon.stub(core.assess.eventFactory, 'createCryptoAnalysisEvent').returns({
86
+ stack: [{ file: `node_modules/${lib}/index.js` }]
87
+ });
88
+ mockCrypto.createHash('MD4', 'foo');
89
+ expect(core.assess.cryptoAnalysis.report).not.to.have.been.called;
90
+ });
91
+ });
92
+ });
93
+ });
94
+ });
95
+
96
+ [
97
+ 'createCipher',
98
+ 'createCipheriv'
99
+ ].forEach((method) => {
100
+ describe(`crypto.${method}()`, function() {
101
+ [
102
+ 'des-ede',
103
+ 'DES-EDE-CBC',
104
+ 'aes128',
105
+ 'rsa',
106
+ 'id-aes128-wrap',
107
+ ].forEach((alg) => {
108
+ it(`doesn't report when algorithm is safe: ${alg}`, function () {
109
+ simulateRequestScope(() => {
110
+ mockCrypto[method](alg, 'foo');
111
+
112
+ expect(core.assess.cryptoAnalysis.report).not.to.have.been.called;
113
+ });
114
+ });
115
+ });
116
+
117
+ [
118
+ 'RC2-64',
119
+ 'rc2-64',
120
+ 'SM4-OFB',
121
+ ].forEach((alg) => {
122
+ it(`reports when algorithm is unsafe: ${alg}`, function () {
123
+ simulateRequestScope(() => {
124
+ mockCrypto[method](alg, 'foo');
125
+
126
+ expect(core.assess.cryptoAnalysis.report).to.have.been.calledWithMatch({
127
+ ruleId: Rule.CRYPTO_BAD_CIPHERS,
128
+ finding: sinon.match({
129
+ args: [{ tracked: false, value: alg }],
130
+ methodName: method,
131
+ moduleName: 'crypto',
132
+ object: { tracked: false, value: 'crypto' },
133
+ result: { tracked: false, value: 'Cipher' },
134
+ source: 'P0',
135
+ stack: sinon.match.array,
136
+ stacktraceOpts: {
137
+ constructorOpt: sinon.match.func,
138
+ }
139
+ }),
140
+ });
141
+ });
142
+ });
143
+ });
144
+ });
145
+ });
146
+ });
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ const { expect } = require('chai');
4
+ const { Rule } = require('@contrast/common');
5
+ const sinon = require('sinon');
6
+ const { initAssessFixture } = require('@contrast/test/fixtures');
7
+
8
+ describe('assess cryptographic analysis Math instrumentation', function () {
9
+ let core, simulateRequestScope;
10
+
11
+ beforeEach(function () {
12
+ ({ core, simulateRequestScope } = initAssessFixture());
13
+ sinon.spy(core.assess.cryptoAnalysis, 'report');
14
+ core.assess.cryptoAnalysis.installers.math.install();
15
+ });
16
+
17
+ afterEach(function () {
18
+ core.assess.cryptoAnalysis.installers.math.uninstall();
19
+ });
20
+
21
+ describe('Math.random()', function () {
22
+ it('reports when', function () {
23
+ simulateRequestScope(() => {
24
+ Math.random();
25
+ expect(core.assess.cryptoAnalysis.report).to.have.been.calledWithMatch({
26
+ ruleId: Rule.CRYPTO_WEAK_RANDOMNESS,
27
+ finding: sinon.match({
28
+ args: [],
29
+ methodName: 'random',
30
+ moduleName: 'global.Math',
31
+ object: { tracked: false, value: 'global.Math' },
32
+ result: { tracked: false, value: sinon.match.string },
33
+ source: 'A',
34
+ stack: sinon.match.array,
35
+ stacktraceOpts: {
36
+ constructorOpt: sinon.match.func,
37
+ },
38
+ })
39
+ });
40
+ });
41
+ });
42
+
43
+ [
44
+ 'node_modules/node-uuid/',
45
+ 'browserify'
46
+ ].forEach((lib) => {
47
+ it('will not report when library is trusted', function () {
48
+ core.config.setValue('assess.stacktraces', 'ALL');
49
+ sinon.stub(core.assess.eventFactory, 'createCryptoAnalysisEvent').returns({
50
+ stack: [{ file: `${lib}/index.js` }],
51
+ });
52
+ simulateRequestScope(() => {
53
+ Math.random();
54
+ expect(core.logger.trace).to.have.been.calledWith(
55
+ { funcKey: 'assess-cryptographic-analysis:global.Math.random' },
56
+ 'skipping reporting for %s - trusting %s',
57
+ 'crypto-weak-randomness',
58
+ lib,
59
+ );
60
+ expect(core.assess.cryptoAnalysis.report).not.to.have.been.called;
61
+ });
62
+ });
63
+ });
64
+ });
65
+ });
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ const { expect } = require('chai');
4
+ const proxyquire = require('proxyquire');
5
+ const mocks = require('@contrast/test/mocks');
6
+
7
+ const moduleMock = (moduleName, mock) => (deps) => {
8
+ deps.assess.dataflow[moduleName] = mock[moduleName];
9
+ };
10
+
11
+ describe('assess dataflow', function () {
12
+ let core, dataflowMock, dataflowModule, modulesWithInstall;
13
+
14
+ beforeEach(function () {
15
+ core = mocks.core();
16
+ core.scopes = mocks.scopes();
17
+ core.assess = mocks.assess();
18
+ dataflowMock = core.assess.dataflow;
19
+ dataflowModule = proxyquire('.', {
20
+ './tracker': moduleMock('tracker', dataflowMock),
21
+ './sources': moduleMock('sources', dataflowMock),
22
+ './sinks': moduleMock('sinks', dataflowMock),
23
+ './propagation': moduleMock('propagation', dataflowMock),
24
+ });
25
+ modulesWithInstall = ['sources', 'sinks', 'propagation'];
26
+ });
27
+
28
+ it('installs the components', function () {
29
+ dataflowModule(core).install();
30
+
31
+ modulesWithInstall.forEach((module) => {
32
+ expect(dataflowMock[module].install).to.have.been.calledOnce;
33
+ });
34
+ });
35
+ });
36
+
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ const { expect } = require('chai');
4
+ const proxyquire = require('proxyquire');
5
+ const mocks = require('@contrast/test/mocks');
6
+
7
+ const moduleMock = (moduleName, mock) => (deps) => {
8
+ deps.assess.dataflow.propagation[moduleName] = mock[moduleName];
9
+ };
10
+
11
+ describe('assess dataflow propagation', function () {
12
+ let core, propagationMock, propagationModule, modulesWithInstall, modulesWithUninstall;
13
+
14
+ beforeEach(function () {
15
+ core = mocks.core();
16
+ core.assess = mocks.assess();
17
+ core.depHooks = mocks.depHooks();
18
+ core.patcher = mocks.patcher();
19
+ core.scopes = mocks.scopes();
20
+
21
+ propagationMock = core.assess.dataflow.propagation;
22
+ propagationModule = proxyquire('.', {
23
+ './install/contrast-methods': moduleMock('contrastMethodsInstrumentation', propagationMock),
24
+ './install/buffer': moduleMock('bufferInstrumentation', propagationMock),
25
+ './install/ejs': moduleMock('ejsInstrumentation', propagationMock),
26
+ './install/pug': moduleMock('pugInstrumentation', propagationMock),
27
+ './install/string': moduleMock('stringInstrumentation', propagationMock),
28
+ './install/url': moduleMock('urlInstrumentation', propagationMock),
29
+ './install/validator': moduleMock('validatorInstrumentation', propagationMock),
30
+ './install/array-prototype-join': moduleMock('arrayJoin', propagationMock),
31
+ './install/decode-uri-component': moduleMock('decodeURIComponent', propagationMock),
32
+ './install/encode-uri': moduleMock('encodeURI', propagationMock),
33
+ './install/escape-html': moduleMock('escapeHtml', propagationMock),
34
+ './install/escape': moduleMock('escape', propagationMock),
35
+ './install/handlebars-utils-escape-expression': moduleMock('handlebarsEscapeExpression', propagationMock),
36
+ './install/mongoose': moduleMock('mongooseInstrumentation', propagationMock),
37
+ './install/mustache-escape': moduleMock('mustacheEscape', propagationMock),
38
+ './install/mysql-connection-escape': moduleMock('mysqlEscape', propagationMock),
39
+ './install/pug-runtime-escape': moduleMock('pugRuntimeEscape', propagationMock),
40
+ './install/sql-template-strings': moduleMock('sqlTemplateStrings', propagationMock),
41
+ './install/unescape': moduleMock('unescape', propagationMock),
42
+ './install/querystring': moduleMock('querystringInstrumentation', propagationMock),
43
+ './install/sequelize': moduleMock('sequelizeInstrumentation', propagationMock),
44
+ './install/JSON': moduleMock('jsonInstrumentation', propagationMock),
45
+ './install/reg-exp-prototype-exec': moduleMock('regExpExec', propagationMock),
46
+ './install/joi': moduleMock('joiInstrumentation', propagationMock),
47
+ './install/util-format': moduleMock('utilFormatInstrumentation', propagationMock)
48
+ });
49
+ modulesWithInstall = [
50
+ 'contrastMethodsInstrumentation',
51
+ 'ejsInstrumentation',
52
+ 'pugInstrumentation',
53
+ 'stringInstrumentation',
54
+ 'urlInstrumentation',
55
+ 'validatorInstrumentation',
56
+ 'arrayJoin',
57
+ 'encodeURI',
58
+ 'decodeURIComponent',
59
+ 'escapeHtml',
60
+ 'escape',
61
+ 'handlebarsEscapeExpression',
62
+ 'mongooseInstrumentation',
63
+ 'mustacheEscape',
64
+ 'mysqlEscape',
65
+ 'pugRuntimeEscape',
66
+ 'sqlTemplateStrings',
67
+ 'unescape',
68
+ 'querystringInstrumentation',
69
+ 'jsonInstrumentation',
70
+ 'regExpExec',
71
+ 'joiInstrumentation'
72
+ ];
73
+ modulesWithUninstall = [
74
+ 'contrastMethodsInstrumentation',
75
+ 'stringInstrumentation',
76
+ 'arrayJoin',
77
+ 'encodeURI',
78
+ 'decodeURIComponent',
79
+ 'escape',
80
+ 'unescape',
81
+ 'jsonInstrumentation',
82
+ 'regExpExec'
83
+ ];
84
+ });
85
+
86
+ it('installs the components', function () {
87
+ propagationModule(core).install();
88
+
89
+ modulesWithInstall.forEach((module) => {
90
+ expect(propagationMock[module].install).to.have.been.calledOnce;
91
+ });
92
+ });
93
+
94
+ it('uninstalls the components', function () {
95
+ propagationModule(core).uninstall();
96
+
97
+ modulesWithUninstall.forEach((module) => {
98
+ if (propagationMock[module].uninstall) {
99
+ expect(propagationMock[module].uninstall).to.have.been.calledOnce;
100
+ }
101
+ });
102
+ });
103
+ });
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ const sinon = require('sinon');
4
+ const { expect } = require('chai');
5
+ const { initAssessFixture } = require('@contrast/test/fixtures');
6
+
7
+ describe('assess dataflow propagation JSON', function () {
8
+ let core, instr;
9
+
10
+ beforeEach(function () {
11
+ ({ core } = initAssessFixture());
12
+ instr = core.assess.dataflow.propagation.jsonInstrumentation;
13
+ });
14
+
15
+ const propagatorList = [
16
+ 'stringify',
17
+ 'parse'
18
+ ];
19
+
20
+ it('composes different installers', function () {
21
+ propagatorList.forEach((name) => {
22
+ expect(instr[name]).to.have.property('install').and.be.a('function');
23
+ expect(instr[name]).to.have.property('uninstall').and.be.a('function');
24
+ });
25
+ });
26
+
27
+ it('dispatches installation to sub-components', function () {
28
+ const installs = [];
29
+ const uninstalls = [];
30
+ // stub these to prevent side effects
31
+ propagatorList.forEach((name) => {
32
+ const instr = core.assess.dataflow.propagation.jsonInstrumentation;
33
+ installs.push(sinon.stub(instr[name], 'install'));
34
+ uninstalls.push(sinon.stub(instr[name], 'uninstall'));
35
+ });
36
+
37
+ instr.install();
38
+ instr.uninstall();
39
+
40
+ expect(installs).to.have.lengthOf(2);
41
+ installs.forEach((installer) => {
42
+ expect(installer).to.have.been.called;
43
+ });
44
+ expect(uninstalls).to.have.lengthOf(2);
45
+ uninstalls.forEach((installer) => {
46
+ expect(installer).to.have.been.called;
47
+ });
48
+ });
49
+ });
50
+
@@ -0,0 +1,232 @@
1
+ 'use strict';
2
+
3
+ const { expect } = require('chai');
4
+ const { getKeyValueIndices } = require('./parse-fn');
5
+
6
+ describe('assess dataflow propagation JSON getValueIndexes', function () {
7
+ const obj = {
8
+ prop1: 'test',
9
+ prop2: 'test2',
10
+ test2: '',
11
+ arr: [{ name: { prop3: 'test3' } }, 2, 'test4'],
12
+ nested: { prop4: 'prop' },
13
+ prop5: 'test5',
14
+ obj: {
15
+ name: 'john',
16
+ 0: ['0', -1, -10, '-10'],
17
+ '': { '&&': '{{', '{}': ',,' },
18
+ },
19
+ };
20
+
21
+ it('should parse a string', function () {
22
+ const result = getKeyValueIndices('"hello"');
23
+ expect(result).to.eql([{ key: '', value: [1, 5] }]);
24
+ });
25
+
26
+ it('should parse a string without quotation marks', function () {
27
+ const result = getKeyValueIndices('hello');
28
+ expect(result).to.eql([{ key: '', value: [0, 4] }]);
29
+ });
30
+
31
+ it('should parse true', function () {
32
+ const result = getKeyValueIndices('true');
33
+ expect(result).to.eql([{ key: '', value: [0, 3] }]);
34
+ });
35
+
36
+ it('should parse false', function () {
37
+ const result = getKeyValueIndices('false');
38
+ expect(result).to.eql([{ key: '', value: [0, 4] }]);
39
+ });
40
+
41
+ it('should parse a number', function () {
42
+ const result = getKeyValueIndices('1231');
43
+ expect(result).to.eql([{ key: '', value: [0, 3] }]);
44
+ });
45
+
46
+ it('should parse a negative number', function () {
47
+ const result = getKeyValueIndices('-1231');
48
+ expect(result).to.eql([{ key: '', value: [0, 4] }]);
49
+ });
50
+
51
+ it('should parse an array', function () {
52
+ const result = getKeyValueIndices(
53
+ '[1, 2, 3, null, true, false, {}, [], ["a"]]');
54
+
55
+ expect(result).to.eql([
56
+ { key: [null, null], value: [1, 1] },
57
+ { key: [null, null], value: [4, 4] },
58
+ { key: [null, null], value: [7, 7] },
59
+ { key: [null, null], value: [10, 13] },
60
+ { key: [null, null], value: [16, 19] },
61
+ { key: [null, null], value: [22, 26] },
62
+ { key: [null, null], value: [29, 30] },
63
+ { key: [null, null], value: [33, 34] },
64
+ { key: [null, null], value: [39, 39] },
65
+ { key: [null, null], value: [37, 41] },
66
+ { key: '', value: [0, 42] },
67
+ ]);
68
+ });
69
+
70
+ it('should parse an object', function () {
71
+ const result = getKeyValueIndices(JSON.stringify(obj));
72
+
73
+ expect(result).to.eql([
74
+ { key: [2, 6], value: [10, 13] },
75
+ { key: [17, 21], value: [25, 29] },
76
+ { key: [33, 37], value: [null, null] },
77
+ { key: [60, 64], value: [68, 72] },
78
+ { key: [52, 55], value: [58, 74] },
79
+ { key: [null, null], value: [50, 75] },
80
+ { key: [null, null], value: [77, 77] },
81
+ { key: [null, null], value: [80, 84] },
82
+ { key: [44, 46], value: [49, 86] },
83
+ { key: [99, 103], value: [107, 110] },
84
+ { key: [89, 94], value: [97, 112] },
85
+ { key: [115, 119], value: [123, 127] },
86
+ { key: [null, null], value: [143, 143] },
87
+ { key: [null, null], value: [146, 147] },
88
+ { key: [null, null], value: [149, 151] },
89
+ { key: [null, null], value: [154, 156] },
90
+ { key: [138, 138], value: [141, 158] },
91
+ { key: [161, 164], value: [168, 171] },
92
+ { key: [179, 180], value: [184, 185] },
93
+ { key: [189, 190], value: [194, 195] },
94
+ { key: [null, null], value: [177, 197] },
95
+ { key: [131, 133], value: [136, 198] },
96
+ { key: '', value: [0, 199] },
97
+ ]);
98
+ });
99
+
100
+ it('should parse an object with spaces', function () {
101
+ const result = getKeyValueIndices(JSON.stringify(obj, null, ' '));
102
+
103
+ expect(result).to.eql([
104
+ {
105
+ key: [6, 10],
106
+ value: [15, 18],
107
+ },
108
+ {
109
+ key: [26, 30],
110
+ value: [35, 39],
111
+ },
112
+ {
113
+ key: [47, 51],
114
+ value: [null, null],
115
+ },
116
+ {
117
+ key: [111, 115],
118
+ value: [120, 124],
119
+ },
120
+ {
121
+ key: [89, 92],
122
+ value: [96, 136],
123
+ },
124
+ {
125
+ key: [null, null],
126
+ value: [77, 144],
127
+ },
128
+ {
129
+ key: [null, null],
130
+ value: [153, 153],
131
+ },
132
+ {
133
+ key: [null, null],
134
+ value: [163, 167],
135
+ },
136
+ {
137
+ key: [63, 65],
138
+ value: [69, 173],
139
+ },
140
+ {
141
+ key: [198, 202],
142
+ value: [207, 210],
143
+ },
144
+ {
145
+ key: [180, 185],
146
+ value: [189, 216],
147
+ },
148
+ {
149
+ key: [223, 227],
150
+ value: [232, 236],
151
+ },
152
+ {
153
+ key: [null, null],
154
+ value: [275, 275],
155
+ },
156
+ {
157
+ key: [null, null],
158
+ value: [288, 289],
159
+ },
160
+ {
161
+ key: [null, null],
162
+ value: [301, 303],
163
+ },
164
+ {
165
+ key: [null, null],
166
+ value: [316, 318],
167
+ },
168
+ {
169
+ key: [259, 259],
170
+ value: [263, 327],
171
+ },
172
+ {
173
+ key: [337, 340],
174
+ value: [345, 348],
175
+ },
176
+ {
177
+ key: [374, 375],
178
+ value: [380, 381],
179
+ },
180
+ {
181
+ key: [395, 396],
182
+ value: [401, 402],
183
+ },
184
+ {
185
+ key: [null, null],
186
+ value: [362, 411],
187
+ },
188
+ {
189
+ key: [244, 246],
190
+ value: [250, 416],
191
+ },
192
+ {
193
+ key: '',
194
+ value: [0, 418],
195
+ },
196
+ ]);
197
+ });
198
+
199
+ it('should parse escaped values', function () {
200
+ const data = {
201
+ '"': "na\"'me",
202
+ '\\&': '&',
203
+ };
204
+
205
+ const result = getKeyValueIndices(JSON.stringify(data));
206
+
207
+ // `{"\\"":"na\\"'me","\\\\&":"&"}`
208
+ expect(result).to.eql([
209
+ { key: [2, 3], value: [7, 13] },
210
+ { key: [17, 19], value: [23, 27] },
211
+ { key: '', value: [0, 29] },
212
+ ]);
213
+ });
214
+
215
+ it('should parse decimal numbers', function () {
216
+ const data = {
217
+ a: 0.11,
218
+ b: 1.01,
219
+ c: 0.00001,
220
+ };
221
+
222
+ const result = getKeyValueIndices(JSON.stringify(data));
223
+
224
+ // '{"a":0.11,"b":1.01,"c":0.00001}'
225
+ expect(result).to.eql([
226
+ { key: [2, 2], value: [5, 8] },
227
+ { key: [11, 11], value: [14, 17] },
228
+ { key: [20, 20], value: [23, 29] },
229
+ { key: '', value: [0, 30] },
230
+ ]);
231
+ });
232
+ });