From b3171004a6a427a74d65aee3d311315691b635cc Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Wed, 12 May 2021 14:46:08 -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 | 67 +++++++++-------- test/core/export.js | 2 +- test/core/public/configure.js | 11 ++- test/core/public/get-rules.js | 29 ++++++-- test/core/public/run-rules.js | 17 +++-- test/core/utils/respondable.js | 76 ++++++++------------ test/mock/frames/responder.html | 2 +- test/mock/frames/results-timeout.html | 2 +- test/mock/frames/send-command-to-parent.html | 21 ++++++ test/mock/frames/throwing.html | 2 +- test/version.js | 2 +- 12 files changed, 136 insertions(+), 102 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 a2c2a0c276..51c546f2b8 100644 --- a/lib/core/utils/respondable.js +++ b/lib/core/utils/respondable.js @@ -45,10 +45,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; @@ -158,7 +155,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 ef124a5e74..e4536de604 100644 --- a/test/core/base/audit.js +++ b/test/core/base/audit.js @@ -1,6 +1,7 @@ /*global Audit, Rule, Promise */ describe('Audit', function() { 'use strict'; + var ver = axe.version.substring(0, axe.version.lastIndexOf('.')); var a, getFlattenedTree; var isNotCalled = function(err) { @@ -117,7 +118,9 @@ describe('Audit', function() { audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/target?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/target?application=axeAPI' }); }); it('should use changed branding', function() { @@ -133,7 +136,9 @@ describe('Audit', function() { audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { helpUrl: - 'https://dequeuniversity.com/rules/thing/x.y/target?application=axeAPI' + 'https://dequeuniversity.com/rules/thing/' + + ver + + '/target?application=axeAPI' }); }); it('should use changed application', function() { @@ -149,7 +154,9 @@ describe('Audit', function() { audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/target?application=thing' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/target?application=thing' }); }); @@ -161,7 +168,9 @@ describe('Audit', function() { selector: 'bob', metadata: { helpUrl: - 'https://dequeuniversity.com/rules/myproject/x.y/target1?application=axeAPI' + 'https://dequeuniversity.com/rules/myproject/' + + ver + + '/target1?application=axeAPI' } }); audit.addRule({ @@ -172,7 +181,9 @@ 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); @@ -182,11 +193,15 @@ 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() { @@ -207,24 +222,6 @@ describe('Audit', function() { '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(); @@ -258,7 +255,9 @@ describe('Audit', function() { audit._constructHelpUrls(); assert.deepEqual(audit.data.rules.target, { helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/target?application=axeAPI&lang=de' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/target?application=axeAPI&lang=de' }); }); }); @@ -298,7 +297,9 @@ describe('Audit', function() { }); assert.deepEqual(audit.data.rules.target, { helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/target?application=thing' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/target?application=thing' }); }); it('should call _constructHelpUrls even when nothing changed', function() { @@ -313,7 +314,9 @@ describe('Audit', function() { audit.setBranding(undefined); assert.deepEqual(audit.data.rules.target, { helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/target?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/target?application=axeAPI' }); }); it('should not replace custom set branding', function() { @@ -324,7 +327,9 @@ describe('Audit', function() { selector: 'bob', metadata: { helpUrl: - 'https://dequeuniversity.com/rules/customer-x/x.y/target?application=axeAPI' + 'https://dequeuniversity.com/rules/customer-x/' + + ver + + '/target?application=axeAPI' } }); audit.setBranding({ @@ -333,7 +338,9 @@ 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 4f0c918ce0..4ce6eab260 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 1e47b5f4b1..9170ff441c 100644 --- a/test/core/public/configure.js +++ b/test/core/public/configure.js @@ -3,6 +3,7 @@ describe('axe.configure', function() { 'use strict'; var fixture = document.getElementById('fixture'); var axeVersion = axe.version; + var ver = axe.version.substring(0, axe.version.lastIndexOf('.')); afterEach(function() { fixture.innerHTML = ''; @@ -70,7 +71,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: { @@ -80,7 +81,9 @@ 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' ); }); @@ -103,7 +106,9 @@ 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' ); }); diff --git a/test/core/public/get-rules.js b/test/core/public/get-rules.js index fb834b1c93..775d62693d 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({ @@ -46,7 +47,9 @@ describe('axe.getRules', function() { assert.equal(retValue[0].help, 'halp'); assert.equal( retValue[0].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule1?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/awesomeRule1?application=axeAPI' ); assert.deepEqual(retValue[0].tags, ['tag1']); @@ -55,7 +58,9 @@ describe('axe.getRules', function() { assert.equal(retValue[1].help, 'halp me!'); assert.equal( retValue[1].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/awesomeRule2?application=axeAPI' ); assert.deepEqual(retValue[1].tags, ['tag1', 'tag2']); @@ -67,7 +72,9 @@ describe('axe.getRules', function() { assert.equal(retValue[0].help, 'halp me!'); assert.equal( retValue[0].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/awesomeRule2?application=axeAPI' ); assert.deepEqual(retValue[0].tags, ['tag1', 'tag2']); }); @@ -85,7 +92,9 @@ describe('axe.getRules', function() { assert.equal(retValue[0].help, 'halp'); assert.equal( retValue[0].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule1?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/awesomeRule1?application=axeAPI' ); assert.deepEqual(retValue[0].tags, ['tag1']); @@ -94,7 +103,9 @@ describe('axe.getRules', function() { assert.equal(retValue[1].help, 'halp me!'); assert.equal( retValue[1].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/awesomeRule2?application=axeAPI' ); assert.deepEqual(retValue[1].tags, ['tag1', 'tag2']); }); @@ -106,7 +117,9 @@ describe('axe.getRules', function() { assert.equal(retValue[0].help, 'halp'); assert.equal( retValue[0].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule1?application=axeAPI' + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/awesomeRule1?application=axeAPI' ); assert.deepEqual(retValue[0].tags, ['tag1']); @@ -115,7 +128,9 @@ describe('axe.getRules', function() { assert.equal(retValue[1].help, 'halp me!'); assert.equal( retValue[1].helpUrl, - 'https://dequeuniversity.com/rules/axe/x.y/awesomeRule2?application=axeAPI' + '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 a7ba070e5d..56259347ae 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('.')); // These tests can sometimes be flaky in IE, allow for up to 3 retries if (axe.testUtils.isIE11) { @@ -206,7 +207,9 @@ describe('runRules', function() { { id: 'div#target', helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/div#target?application=axeAPI', + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/div#target?application=axeAPI', pageLevel: false, impact: null, inapplicable: [], @@ -241,7 +244,9 @@ describe('runRules', function() { { id: 'first-div', helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/first-div?application=axeAPI', + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/first-div?application=axeAPI', pageLevel: false, impact: null, inapplicable: [], @@ -493,7 +498,9 @@ describe('runRules', function() { { id: 'div#target', helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/div#target?application=axeAPI', + 'https://dequeuniversity.com/rules/axe/' + + ver + + '/div#target?application=axeAPI', pageLevel: false, foo: 'bar', stuff: 'blah', @@ -530,7 +537,9 @@ describe('runRules', function() { { id: 'first-div', helpUrl: - 'https://dequeuniversity.com/rules/axe/x.y/first-div?application=axeAPI', + '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 6843b48eaa..7d531c09d2 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() { @@ -117,28 +122,7 @@ describe('axe.utils.respondable', function() { event.initEvent('message', true, true); event.data = JSON.stringify({ _respondable: true, - _source: 'axeAPI.2.0.0', - 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', + _source: 'axeAPI.' + axe.version, message: 'Help us Obi-Wan', uuid: mockUUID }); @@ -152,30 +136,6 @@ describe('axe.utils.respondable', function() { 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', - 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); - axe.version = v; - }); - it('should reject messages if the axe version is different', function() { var success = true; var event = document.createEvent('Event'); @@ -298,7 +258,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, error: { name: 'ReferenceError', message: 'The exhaust port is open!', @@ -326,7 +286,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, error: { name: 'evil', message: 'The exhaust port is open!', @@ -489,5 +449,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 e382bae67c..476cc018bc 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 011850f8b3..d3918fbc95 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..1a45e79121 --- /dev/null +++ b/test/mock/frames/send-command-to-parent.html @@ -0,0 +1,21 @@ + + + + Double responding frame + + + + + + + + + + diff --git a/test/mock/frames/throwing.html b/test/mock/frames/throwing.html index 5618d35af1..3ec4239052 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 290b8dcd29..0321016fb4 100644 --- a/test/version.js +++ b/test/version.js @@ -2,4 +2,4 @@ // This enables free communication between frames with // to the current version of axe: -axe.version = 'x.y.z'; +axe.version = '3.4.2';