Skip to content

Commit

Permalink
Merge pull request #1878 from dequelabs/fix-1754-poison-postmessage
Browse files Browse the repository at this point in the history
fix(respondable): ignore messages from other applications
  • Loading branch information
AutoSponge committed Nov 6, 2019
2 parents de9885d + c79277e commit b04b594
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 13 deletions.
20 changes: 19 additions & 1 deletion lib/core/utils/respondable.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@
_keepalive: keepalive
};

var axeRespondables = axe._cache.get('axeRespondables');
if (!axeRespondables) {
axeRespondables = {};
axe._cache.set('axeRespondables', axeRespondables);
}
axeRespondables[uuid] = true;
if (typeof callback === 'function') {
messages[uuid] = callback;
}
Expand Down Expand Up @@ -213,6 +219,18 @@

var uuid = data.uuid;

/**
* NOTE: messages from other contexts (frames) in response
* to a message should not contain a topic. We ignore these
* messages to prevent rogue postMessage handlers reflecting
* our messages.
* @see https://github.com/dequelabs/axe-core/issues/1754
*/
var axeRespondables = axe._cache.get('axeRespondables') || {};
if (axeRespondables[uuid] && data.topic && e.source !== window) {
return;
}

var keepalive = data._keepalive;
var callback = messages[uuid];

Expand All @@ -230,7 +248,7 @@
try {
publish(e.source, data, keepalive);
} catch (err) {
post(e.source, data.topic, err, uuid, false);
post(e.source, null, err, uuid, false);
}
}
},
Expand Down
42 changes: 42 additions & 0 deletions test/core/public/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,4 +534,46 @@ describe('axe.run iframes', function() {
frame.src = '../mock/frames/test.html';
fixture.appendChild(frame);
});

it('ignores unexpected messages from non-axe iframes', function(done) {
var frame = document.createElement('iframe');

frame.addEventListener('load', function() {
var safetyTimeout = window.setTimeout(function() {
done('timeout');
}, 1000);

axe.run('#fixture', {}, function(err, result) {
assert.isNull(err);
assert.equal(result.violations.length, 1);
window.clearTimeout(safetyTimeout);
done();
});
});

frame.src = '../mock/frames/with-echo.html';
fixture.appendChild(frame);
});

it('ignores unexpected messages from axe iframes', function(done) {
var frame = document.createElement('iframe');

frame.addEventListener('load', function() {
var safetyTimeout = window.setTimeout(function() {
done('timeout');
}, 1000);
if (!axe._audit) {
throw new Error('no _audit');
}
axe.run('#fixture', {}, function(err, result) {
assert.isNull(err);
assert.equal(result.violations.length, 1);
window.clearTimeout(safetyTimeout);
done();
});
});

frame.src = '../mock/frames/with-echo-axe.html';
fixture.appendChild(frame);
});
});
13 changes: 1 addition & 12 deletions test/core/utils/respondable.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ describe('axe.utils.respondable', function() {
event.data = JSON.stringify({
_respondable: true,
_source: 'axeAPI.2.0.0',
topic: 'Death star',
message: 'Help us Obi-Wan',
uuid: mockUUID
});
Expand All @@ -140,7 +139,6 @@ describe('axe.utils.respondable', function() {
event.data = JSON.stringify({
_respondable: true,
_source: 'axeAPI.x.y.z',
topic: 'Death star',
message: 'Help us Obi-Wan',
uuid: mockUUID
});
Expand All @@ -164,7 +162,6 @@ describe('axe.utils.respondable', function() {
event.data = JSON.stringify({
_respondable: true,
_source: 'axeAPI.2.0.0',
topic: 'Death star',
message: 'Help us Obi-Wan',
uuid: mockUUID
});
Expand All @@ -189,7 +186,6 @@ describe('axe.utils.respondable', function() {
event.data = JSON.stringify({
_respondable: true,
_source: 'axeAPI.2.0.0',
topic: 'Death star',
message: 'Help us Obi-Wan',
uuid: mockUUID
});
Expand All @@ -210,7 +206,6 @@ describe('axe.utils.respondable', function() {
event.initEvent('message', true, true);
event.data = {
_respondable: true,
topic: 'batman',
uuid: mockUUID
};
event.source = window;
Expand All @@ -230,7 +225,6 @@ describe('axe.utils.respondable', function() {
event.data =
JSON.stringify({
_respondable: true,
topic: 'batman',
uuid: mockUUID
}) + 'joker tricks!';
event.source = window;
Expand All @@ -249,8 +243,7 @@ describe('axe.utils.respondable', function() {
event.initEvent('message', true, true);
event.data = '{ "_respondable": true, "topic": "batman" }';
event.data = JSON.stringify({
_respondable: true,
topic: 'batman'
_respondable: true
});
event.source = window;

Expand All @@ -269,7 +262,6 @@ describe('axe.utils.respondable', function() {
event.data = '{ "_respondable": true, "topic": "batman", "uuid": "12" }';
event.data = JSON.stringify({
_respondable: true,
topic: 'batman',
uuid: 'not-' + mockUUID
});
event.source = window;
Expand All @@ -288,7 +280,6 @@ describe('axe.utils.respondable', function() {
event.initEvent('message', true, true);
event.data = '{ "uuid": "48", "topic": "batman" }';
event.data = JSON.stringify({
topic: 'batman',
uuid: mockUUID
});
event.source = window;
Expand All @@ -308,7 +299,6 @@ describe('axe.utils.respondable', function() {
event.data = JSON.stringify({
_respondable: true,
_source: 'axeAPI.2.0.0',
topic: 'Death star',
error: {
name: 'ReferenceError',
message: 'The exhaust port is open!',
Expand Down Expand Up @@ -337,7 +327,6 @@ describe('axe.utils.respondable', function() {
event.data = JSON.stringify({
_respondable: true,
_source: 'axeAPI.2.0.0',
topic: 'Death star',
error: {
name: 'evil',
message: 'The exhaust port is open!',
Expand Down
1 change: 1 addition & 0 deletions test/mock/frames/responder.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
version: '2.0.0'
};
</script>
<script src="../../../tmp/core/base/cache.js"></script>
<script src="../../../lib/core/utils/respondable.js"></script>

<script>
Expand Down
1 change: 1 addition & 0 deletions test/mock/frames/results-timeout.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
version: '2.0.0'
};
</script>
<script src="../../../tmp/core/base/cache.js"></script>
<script src="../../../lib/core/utils/respondable.js"></script>

<script>
Expand Down
1 change: 1 addition & 0 deletions test/mock/frames/throwing.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
version: '2.0.0'
};
</script>
<script src="../../../tmp/core/base/cache.js"></script>
<script src="../../../lib/core/utils/respondable.js"></script>

<script>
Expand Down
41 changes: 41 additions & 0 deletions test/mock/frames/with-echo-axe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Echo frame with axe-core</title>
<meta charset="utf8" />
<script src="../../../axe.js"></script>
<script>
// sync this rule to the one in test/core/public/run.js
axe._load({
rules: [
{
id: 'html',
selector: '#target',
none: ['fred']
}
],
checks: [
{
id: 'fred',
evaluate: function() {
return true;
}
}
]
});
</script>
</head>
<body>
<h1>Frame with axe-core</h1>
<div id="target">Target in iframe</div>
<script>
window.addEventListener(
'message',
function(event) {
window.top.postMessage(event.data, '*');
},
false
);
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions test/mock/frames/with-echo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Echo frame without axe-core</title>
<meta charset="utf8" />
</head>
<body>
<h1>Frame without axe-core</h1>
<div id="target">Target in iframe</div>
<script>
window.addEventListener(
'message',
function(event) {
window.top.postMessage(event.data, '*');
},
false
);
</script>
</body>
</html>

0 comments on commit b04b594

Please sign in to comment.