fix(csp): make CSP reports more detailed, remove sample rate

Fix #3297
This commit is contained in:
Vlad Filippov 2015-12-29 18:41:18 -05:00
Родитель 9dbb9ac48d
Коммит 41d919c629
4 изменённых файлов: 17 добавлений и 53 удалений

Просмотреть файл

@ -72,10 +72,6 @@ var conf = module.exports = convict({
default: false,
doc: 'Only send the "Content-Security-Policy-Report-Only" header'
},
reportSampleRate: {
default: 10,
doc: 'Sample rate at which CSP violation reports should be logged'
},
reportUri: {
default: '/_/csp-violation',
doc: 'Location of "report-uri"'

Просмотреть файл

@ -28,8 +28,7 @@ module.exports = function (config, i18n) {
require('./routes/get-client.json')(i18n),
require('./routes/post-metrics')(),
require('./routes/post-csp')({
path: config.get('csp.reportUri'),
reportSampleRate: config.get('csp.reportSampleRate')
path: config.get('csp.reportUri')
}),
require('./routes/get-metrics-errors')(),
require('./routes/get-openid-login')(config),

Просмотреть файл

@ -9,30 +9,12 @@
module.exports = function (options) {
options = options || {};
/**
* 'reportSampleRate' % of messages.
* @param reportSampleRate
* @returns {boolean}
*/
function isSampledUser() {
// random between 0 and 100, inclusive
var rand = Math.floor(Math.random() * (100 + 1));
return rand < options.reportSampleRate;
}
return {
method: 'post',
path: options.path,
process: function (req, res) {
res.json({result: 'ok'});
// TODO: This is a temporary measure
// Not sure how many CSP errors we will get, for now we rate limit this.
// To avoid overflowing Heka logs rate limit the logging
if (! isSampledUser()) {
return false;
}
if (! req.body || ! req.body['csp-report']) {
return false;
}
@ -42,11 +24,16 @@ module.exports = function (options) {
var report = req.body['csp-report'];
var entry = {
agent: req.get('User-Agent'),
blocked: report['blocked-uri'],
column: report['column-number'],
line: report['line-number'],
op: 'server.csp',
referrer: report['referrer'],
sample: report['script-sample'],
source: report['source-file'],
time: today.toISOString(),
violated: report['violated-directive']
violated: report['violated-directive'],
};
process.stderr.write(JSON.stringify(entry) + '\n');

Просмотреть файл

@ -22,51 +22,33 @@ define([
'csp-report': {
'blocked-uri': 'http://bing.com'
}
}
},
'get': function () {}
};
var mockResponse = {
json: function () {}
};
suite['it drops if no csp-report set'] = function () {
var options = {
reportSampleRate: 100
};
var postCsp = proxyquire(path.join(process.cwd(), 'server', 'lib', 'routes', 'post-csp'), {})(options);
var postCsp = proxyquire(path.join(process.cwd(), 'server', 'lib', 'routes', 'post-csp'), {})();
assert.isFalse(postCsp.process({
body: {}
body: {},
'get': function () {}
}, mockResponse));
assert.isTrue(postCsp.process({
body: {
'csp-report': {}
}
},
'get': function () {}
}, mockResponse));
assert.isTrue(postCsp.process(mockRequest, mockResponse));
};
suite['it allows no messages with 0% sample rate '] = function () {
var options = {
reportSampleRate: 0
};
var postCsp = proxyquire(path.join(process.cwd(), 'server', 'lib', 'routes', 'post-csp'), {})(options);
// check 5 times that all messages come through
assert.isFalse(postCsp.process(mockRequest, mockResponse));
assert.isFalse(postCsp.process(mockRequest, mockResponse));
assert.isFalse(postCsp.process(mockRequest, mockResponse));
assert.isFalse(postCsp.process(mockRequest, mockResponse));
assert.isFalse(postCsp.process(mockRequest, mockResponse));
};
suite['it allows all messages with 100% sample rate'] = function () {
var options = {
reportSampleRate: 100
};
var postCsp = proxyquire(path.join(process.cwd(), 'server', 'lib', 'routes', 'post-csp'), {})(options);
suite['it works with csp reports'] = function () {
var postCsp = proxyquire(path.join(process.cwd(), 'server', 'lib', 'routes', 'post-csp'), {})();
// check 5 times that all messages drop
assert.isTrue(postCsp.process(mockRequest, mockResponse));
assert.isTrue(postCsp.process(mockRequest, mockResponse));