From 9e62c8c42e65e03d32e50a1e2e0dca80b380634e Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Thu, 29 Apr 2021 17:11:01 -0600 Subject: [PATCH] fix: do not allow postMessage with axe version of x.y.z --- lib/core/utils/respondable.js | 7 +- test/core/base/audit.js | 40 ++++------ test/core/export.js | 2 +- test/core/public/configure.js | 7 +- test/core/public/get-rules.js | 15 ++-- test/core/public/run-rules.js | 9 ++- test/core/utils/respondable.js | 79 +++++++------------- test/mock/frames/responder.html | 2 +- test/mock/frames/results-timeout.html | 2 +- test/mock/frames/send-command-to-parent.html | 20 +++++ test/mock/frames/throwing.html | 2 +- test/version.js | 4 +- 12 files changed, 85 insertions(+), 104 deletions(-) create mode 100644 test/mock/frames/send-command-to-parent.html diff --git a/lib/core/utils/respondable.js b/lib/core/utils/respondable.js index ef3af5ecc0..a3896ac4a1 100644 --- a/lib/core/utils/respondable.js +++ b/lib/core/utils/respondable.js @@ -35,10 +35,7 @@ ) { var messageSource = _getSource(); return ( // Check the version matches - postedMessage._source === messageSource || - // Allow free communication with axe test - postedMessage._source === 'axeAPI.x.y.z' || - messageSource === 'axeAPI.x.y.z' + postedMessage._source === messageSource ); } return false; @@ -143,7 +140,7 @@ var topic = data.topic; var subscriber = subscribers[topic]; - if (subscriber) { + if (subscriber && source === window.parent) { var responder = createResponder(source, null, data.uuid); subscriber(data.message, keepalive, responder); } diff --git a/test/core/base/audit.js b/test/core/base/audit.js index 9efd7ee339..8d1acb6cc3 100644 --- a/test/core/base/audit.js +++ b/test/core/base/audit.js @@ -1,6 +1,8 @@ /*global Audit, Rule */ describe('Audit', function () { 'use strict'; + var ver = axe.version.substring(0, axe.version.lastIndexOf('.')); + var a, getFlattenedTree; var isNotCalled = function (err) { throw err || new Error('Reject should not be called'); @@ -95,7 +97,7 @@ describe('Audit', function () { assert.equal(audit.data.rules.target, undefined); audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/target?application=axeAPI' + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/target?application=axeAPI' }); }); it('should use changed branding', function () { @@ -110,7 +112,7 @@ describe('Audit', function () { audit.brand = 'thing'; audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { - helpUrl: 'https://dequeuniversity.com/rules/thing/x.y/target?application=axeAPI' + helpUrl: 'https://dequeuniversity.com/rules/thing/' + ver + '/target?application=axeAPI' }); }); it('should use changed application', function () { @@ -125,7 +127,7 @@ describe('Audit', function () { audit.application = 'thing'; audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/target?application=thing' + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/target?application=thing' }); }); @@ -136,7 +138,7 @@ describe('Audit', function () { matches: 'function () {return "hello";}', selector: 'bob', metadata: { - helpUrl: 'https://dequeuniversity.com/rules/myproject/x.y/target1?application=axeAPI' + helpUrl: 'https://dequeuniversity.com/rules/myproject/' + ver + '/target1?application=axeAPI' } }); audit.addRule({ @@ -147,7 +149,7 @@ describe('Audit', function () { assert.equal( audit.data.rules.target1.helpUrl, - 'https://dequeuniversity.com/rules/myproject/x.y/target1?application=axeAPI' + 'https://dequeuniversity.com/rules/myproject/' + ver + '/target1?application=axeAPI' ); assert.isUndefined(audit.data.rules.target2); @@ -157,11 +159,11 @@ describe('Audit', function () { assert.equal( audit.data.rules.target1.helpUrl, - 'https://dequeuniversity.com/rules/myproject/x.y/target1?application=axeAPI' + 'https://dequeuniversity.com/rules/myproject/' + ver + '/target1?application=axeAPI' ); assert.equal( audit.data.rules.target2.helpUrl, - 'https://dequeuniversity.com/rules/thing/x.y/target2?application=axeAPI' + 'https://dequeuniversity.com/rules/thing/' + ver + '/target2?application=axeAPI' ); }); it('understands prerelease type version numbers', function () { @@ -180,22 +182,6 @@ describe('Audit', function () { assert.equal(audit.data.rules.target.helpUrl, 'https://dequeuniversity.com/rules/axe/3.2/target?application=axeAPI'); }); - it('sets x.y as version for invalid versions', function () { - var tempVersion = axe.version; - var audit = new Audit(); - audit.addRule({ - id: 'target', - matches: 'function () {return "hello";}', - selector: 'bob' - }); - - axe.version = 'in-3.0-valid'; - audit._constructHelpUrls(); - - axe.version = tempVersion; - assert.equal(audit.data.rules.target.helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/target?application=axeAPI'); - }); it('matches major release versions', function () { var tempVersion = axe.version; var audit = new Audit(); @@ -248,7 +234,7 @@ describe('Audit', function () { application: 'thing' }); assert.deepEqual(audit.data.rules.target, { - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/target?application=thing' + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/target?application=thing' }); }); it('should call _constructHelpUrls even when nothing changed', function () { @@ -262,7 +248,7 @@ describe('Audit', function () { assert.equal(audit.data.rules.target, undefined); audit.setBranding(undefined); assert.deepEqual(audit.data.rules.target, { - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/target?application=axeAPI' + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/target?application=axeAPI' }); }); it('should not replace custom set branding', function () { @@ -272,7 +258,7 @@ describe('Audit', function () { matches: 'function () {return "hello";}', selector: 'bob', metadata: { - helpUrl: 'https://dequeuniversity.com/rules/customer-x/x.y/target?application=axeAPI' + helpUrl: 'https://dequeuniversity.com/rules/customer-x/' + ver + '/target?application=axeAPI' } }); audit.setBranding({ @@ -281,7 +267,7 @@ describe('Audit', function () { }); assert.equal( audit.data.rules.target.helpUrl, - 'https://dequeuniversity.com/rules/customer-x/x.y/target?application=axeAPI' + 'https://dequeuniversity.com/rules/customer-x/' + ver + '/target?application=axeAPI' ); }); diff --git a/test/core/export.js b/test/core/export.js index 67abe42e1c..1685b487ca 100644 --- a/test/core/export.js +++ b/test/core/export.js @@ -5,6 +5,6 @@ describe('export', function () { assert.isDefined(window.axe); }); it('should define version', function () { - assert.equal(axe.version, 'x.y.z'); + assert.isNotNull(axe.version); }); }); diff --git a/test/core/public/configure.js b/test/core/public/configure.js index 11995e2bb8..48f33bbe4f 100644 --- a/test/core/public/configure.js +++ b/test/core/public/configure.js @@ -2,6 +2,7 @@ describe('axe.configure', function() { 'use strict'; var fixture = document.getElementById('fixture'); + var ver = axe.version.substring(0, axe.version.lastIndexOf('.')); afterEach(function () { fixture.innerHTML = ''; @@ -59,7 +60,7 @@ describe('axe.configure', function() { }); assert.lengthOf(axe._audit.rules, 1); assert.equal(axe._audit.data.rules.bob.helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/bob?application=axeAPI'); + 'https://dequeuniversity.com/rules/axe/' + ver + '/bob?application=axeAPI'); axe.configure({ branding: { application: 'thing', @@ -67,7 +68,7 @@ describe('axe.configure', function() { } }); assert.equal(axe._audit.data.rules.bob.helpUrl, - 'https://dequeuniversity.com/rules/thung/x.y/bob?application=thing'); + 'https://dequeuniversity.com/rules/thung/' + ver + '/bob?application=thing'); }); it('sets branding on newly configured rules', function () { @@ -86,7 +87,7 @@ describe('axe.configure', function() { }); assert.equal(axe._audit.data.rules.bob.helpUrl, - 'https://dequeuniversity.com/rules/thung/x.y/bob?application=thing'); + 'https://dequeuniversity.com/rules/thung/' + ver + '/bob?application=thing'); }); it('should allow for overwriting of rules', function () { diff --git a/test/core/public/get-rules.js b/test/core/public/get-rules.js index eaad26ddf0..657155f3ed 100644 --- a/test/core/public/get-rules.js +++ b/test/core/public/get-rules.js @@ -1,5 +1,6 @@ describe('axe.getRules', function() { 'use strict'; + var ver = axe.version.substring(0, axe.version.lastIndexOf('.')); beforeEach(function() { axe._load({ @@ -41,13 +42,13 @@ describe('axe.getRules', function() { assert.equal(retValue[0].ruleId, 'awesomeRule1'); assert.equal(retValue[0].description, 'some interesting information'); assert.equal(retValue[0].help, 'halp'); - assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule1?application=axeAPI'); + assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule1?application=axeAPI'); assert.deepEqual(retValue[0].tags, ['tag1']); assert.equal(retValue[1].ruleId, 'awesomeRule2'); assert.equal(retValue[1].description, 'also some interesting information'); assert.equal(retValue[1].help, 'halp me!'); - assert.equal(retValue[1].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI'); + assert.equal(retValue[1].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule2?application=axeAPI'); assert.deepEqual(retValue[1].tags, ['tag1', 'tag2']); retValue = axe.getRules(['tag2']); @@ -56,7 +57,7 @@ describe('axe.getRules', function() { assert.equal(retValue[0].ruleId, 'awesomeRule2'); assert.equal(retValue[0].description, 'also some interesting information'); assert.equal(retValue[0].help, 'halp me!'); - assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI'); + assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule2?application=axeAPI'); assert.deepEqual(retValue[0].tags, ['tag1', 'tag2']); }); @@ -71,13 +72,13 @@ describe('axe.getRules', function() { assert.equal(retValue[0].ruleId, 'awesomeRule1'); assert.equal(retValue[0].description, 'some interesting information'); assert.equal(retValue[0].help, 'halp'); - assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule1?application=axeAPI'); + assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule1?application=axeAPI'); assert.deepEqual(retValue[0].tags, ['tag1']); assert.equal(retValue[1].ruleId, 'awesomeRule2'); assert.equal(retValue[1].description, 'also some interesting information'); assert.equal(retValue[1].help, 'halp me!'); - assert.equal(retValue[1].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI'); + assert.equal(retValue[1].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule2?application=axeAPI'); assert.deepEqual(retValue[1].tags, ['tag1', 'tag2']); }); @@ -86,13 +87,13 @@ describe('axe.getRules', function() { assert.equal(retValue[0].ruleId, 'awesomeRule1'); assert.equal(retValue[0].description, 'some interesting information'); assert.equal(retValue[0].help, 'halp'); - assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule1?application=axeAPI'); + assert.equal(retValue[0].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule1?application=axeAPI'); assert.deepEqual(retValue[0].tags, ['tag1']); assert.equal(retValue[1].ruleId, 'awesomeRule2'); assert.equal(retValue[1].description, 'also some interesting information'); assert.equal(retValue[1].help, 'halp me!'); - assert.equal(retValue[1].helpUrl, 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI'); + assert.equal(retValue[1].helpUrl, 'https://dequeuniversity.com/rules/axe/' + ver + '/awesomeRule2?application=axeAPI'); assert.deepEqual(retValue[1].tags, ['tag1', 'tag2']); }); diff --git a/test/core/public/run-rules.js b/test/core/public/run-rules.js index 15a2ad2511..c280004321 100644 --- a/test/core/public/run-rules.js +++ b/test/core/public/run-rules.js @@ -1,6 +1,7 @@ /*global runRules */ describe('runRules', function () { 'use strict'; + var ver = axe.version.substring(0, axe.version.lastIndexOf('.')); function iframeReady(src, context, id, cb) { var i = document.createElement('iframe'); @@ -158,7 +159,7 @@ describe('runRules', function () { runRules('#fixture', {}, function (results) { assert.deepEqual(JSON.parse(JSON.stringify(results)), [{ id: 'div#target', - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/div#target?application=axeAPI', + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/div#target?application=axeAPI', pageLevel: false, impact: null, inapplicable: [], @@ -184,7 +185,7 @@ describe('runRules', function () { tags: [] }, { id: 'first-div', - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/first-div?application=axeAPI', + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/first-div?application=axeAPI', pageLevel: false, impact: null, inapplicable: [], @@ -378,7 +379,7 @@ describe('runRules', function () { runRules('#fixture', {}, function (results) { assert.deepEqual(JSON.parse(JSON.stringify(results)), [{ id: 'div#target', - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/div#target?application=axeAPI', + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/div#target?application=axeAPI', pageLevel: false, foo: 'bar', stuff: 'blah', @@ -409,7 +410,7 @@ describe('runRules', function () { tags: [] }, { id: 'first-div', - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/first-div?application=axeAPI', + helpUrl: 'https://dequeuniversity.com/rules/axe/' + ver + '/first-div?application=axeAPI', pageLevel: false, bar: 'foo', stuff: 'no', diff --git a/test/core/utils/respondable.js b/test/core/utils/respondable.js index f15fd36827..7f4e2956aa 100644 --- a/test/core/utils/respondable.js +++ b/test/core/utils/respondable.js @@ -6,8 +6,11 @@ describe('axe.utils.respondable', function () { var getMockUUID = function () { return mockUUID; }; + var version; + var fixture = document.querySelector('#fixture'); beforeEach(function () { + version = axe.version; originalUUID = window.uuid.v1; window.uuid.v1 = getMockUUID; mockUUID = originalUUID(); @@ -15,6 +18,8 @@ describe('axe.utils.respondable', function () { afterEach(function () { window.uuid.v1 = originalUUID; + axe.version = version; + fixture.innerHTML = ''; }); it('should be a function', function () { @@ -118,53 +123,7 @@ describe('axe.utils.respondable', function () { event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, - _source: 'axeAPI.2.0.0', - topic: 'Death star', - message: 'Help us Obi-Wan', - uuid: mockUUID - }); - event.source = window; - - axe.utils.respondable(window, 'Death star', null, true, function (data) { - success = true; - assert.equal(data, 'Help us Obi-Wan'); - }); - document.dispatchEvent(event); - assert.isTrue(success); - }); - - it('should allow messages with _source axeAPI.x.y.z', function () { - var success = false; - var event = document.createEvent('Event'); - // Define that the event name is 'build'. - event.initEvent('message', true, true); - event.data = JSON.stringify({ - _respondable: true, - _source: 'axeAPI.x.y.z', - topic: 'Death star', - message: 'Help us Obi-Wan', - uuid: mockUUID - }); - event.source = window; - - axe.utils.respondable(window, 'Death star', null, true, function (data) { - success = true; - assert.equal(data, 'Help us Obi-Wan'); - }); - document.dispatchEvent(event); - assert.isTrue(success); - }); - - it('should allow messages if the axe version is x.y.z', function () { - var success = false; - var event = document.createEvent('Event'); - var v = axe.version; - axe.version = 'x.y.z'; - // Define that the event name is 'build'. - event.initEvent('message', true, true); - event.data = JSON.stringify({ - _respondable: true, - _source: 'axeAPI.2.0.0', + _source: 'axeAPI.' + axe.version, topic: 'Death star', message: 'Help us Obi-Wan', uuid: mockUUID @@ -177,13 +136,11 @@ describe('axe.utils.respondable', function () { }); document.dispatchEvent(event); assert.isTrue(success); - axe.version = v; }); it('should reject messages if the axe version is different', function () { var success = true; var event = document.createEvent('Event'); - var v = axe.version; axe.version = '1.0.0'; // Define that the event name is 'build'. event.initEvent('message', true, true); @@ -201,7 +158,6 @@ describe('axe.utils.respondable', function () { }); document.dispatchEvent(event); assert.isTrue(success); - axe.version = v; }); it('should reject messages that are that are not strings', function () { @@ -311,7 +267,7 @@ describe('axe.utils.respondable', function () { event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, - _source: 'axeAPI.2.0.0', + _source: 'axeAPI.' + axe.version, topic: 'Death star', error: { name: 'ReferenceError', @@ -340,7 +296,7 @@ describe('axe.utils.respondable', function () { event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, - _source: 'axeAPI.2.0.0', + _source: 'axeAPI.' + axe.version, topic: 'Death star', error: { name: 'evil', @@ -490,6 +446,25 @@ describe('axe.utils.respondable', function () { ); }); + it('does not run if the command did not come from the parent iframe', function(done) { + var published = false; + axe.utils.respondable.subscribe('catman', function () { + published = true; + }); + + var frame = document.createElement('iframe'); + frame.addEventListener('load', function () { + axe._tree = axe.utils.getFlattenedTree(document.documentElement); + setTimeout(function () { + assert.ok(!published, 'Subscriber should not be called'); + done(); + }, 10); + }); + + frame.id = 'level0'; + frame.src = '../mock/frames/send-command-to-parent.html'; + fixture.appendChild(frame); + }); }); }); diff --git a/test/mock/frames/responder.html b/test/mock/frames/responder.html index 6b1d4b14b0..ca81efdfb4 100644 --- a/test/mock/frames/responder.html +++ b/test/mock/frames/responder.html @@ -8,7 +8,7 @@ diff --git a/test/mock/frames/results-timeout.html b/test/mock/frames/results-timeout.html index 948bbabfff..f7e9a4744d 100644 --- a/test/mock/frames/results-timeout.html +++ b/test/mock/frames/results-timeout.html @@ -8,7 +8,7 @@ diff --git a/test/mock/frames/send-command-to-parent.html b/test/mock/frames/send-command-to-parent.html new file mode 100644 index 0000000000..215e64744a --- /dev/null +++ b/test/mock/frames/send-command-to-parent.html @@ -0,0 +1,20 @@ + + + + Double responding frame + + + + + + + + + diff --git a/test/mock/frames/throwing.html b/test/mock/frames/throwing.html index bc64ba2cb3..99155817be 100644 --- a/test/mock/frames/throwing.html +++ b/test/mock/frames/throwing.html @@ -8,7 +8,7 @@ diff --git a/test/version.js b/test/version.js index afcfe8c29e..f93ccdd63c 100644 --- a/test/version.js +++ b/test/version.js @@ -1,5 +1,5 @@ /*global axe */ -// This enables free communication between frames with +// This enables free communication between frames with // to the current version of axe: -axe.version = 'x.y.z'; +axe.version = '3.0.3';