Commit 0d95508e authored by Robert Knight's avatar Robert Knight

Only import known config params from the host page

The previous method of importing config params allowed the host page to
override any configuration parameter provided by the service hosting the
client's app.html file, potentially introducing vulnerabilities.

This PR limits the client to importing only config parameters from a
whitelist. This also has the benefit of clearly documenting all the
parameters that can come from the host page in one place in the code.
parent 547c01cb
'use strict';
var queryString = require('query-string');
var addAnalytics = require('./ga');
require('../shared/polyfills');
var raven;
// Initialize Raven. This is required at the top of this file
// so that it happens early in the app's startup flow
var configParam = queryString.parse(window.location.search).config || 'null';
var settings = require('../shared/settings')(document);
Object.assign(settings, JSON.parse(configParam));
if (settings.raven) {
// Initialize Raven. This is required at the top of this file
// so that it happens early in the app's startup flow
raven = require('./raven');
raven.init(settings.raven);
}
var hostPageConfig = require('./host-config');
Object.assign(settings, hostPageConfig(window));
// Disable Angular features that are not compatible with CSP.
//
// See https://docs.angularjs.org/api/ng/directive/ngCsp
......
'use strict';
var queryString = require('query-string');
/**
* Return the app configuration specified by the frame embedding the Hypothesis
* client.
*/
function hostPageConfig(window) {
var configJSON = queryString.parse(window.location.search).config;
var config = JSON.parse(configJSON || '{}');
// Known configuration parameters which we will import from the host page.
// Note that since the host page is untrusted code, the filtering needs to
// be done here.
var paramWhiteList = [
// Direct-linked annotation ID
'annotations',
// Config params documented at
// https://github.com/hypothesis/client/blob/master/docs/config.md
'openLoginForm',
'openSidebar',
'showHighlights',
];
return Object.keys(config).reduce(function (result, key) {
if (paramWhiteList.indexOf(key) !== -1) {
result[key] = config[key];
}
return result;
}, {});
}
module.exports = hostPageConfig;
'use strict';
var hostPageConfig = require('../host-config');
function fakeWindow(config) {
return {
location: {
search: '?config=' + JSON.stringify(config),
},
};
}
describe('hostPageConfig', function () {
it('parses config from location string and returns whitelisted params', function () {
var window_ = fakeWindow({
annotations: '1234',
openSidebar: true,
openLoginForm: true,
showHighlights: true,
});
assert.deepEqual(hostPageConfig(window_), {
annotations: '1234',
openSidebar: true,
openLoginForm: true,
showHighlights: true,
});
});
it('ignores non-whitelisted config params', function () {
var window_ = fakeWindow({
apiUrl: 'https://not-the-hypothesis/api',
});
assert.deepEqual(hostPageConfig(window_), {});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment