Merge pull request #69 from superhumane/xss_fix

Escape strings in HTML output (XSS fix)
This commit is contained in:
Miroslav Bajtoš 2018-01-25 14:37:30 +01:00 committed by GitHub
commit 89b6183704
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 5 deletions

1
.npmrc Normal file
View File

@ -0,0 +1 @@
package-lock=false

View File

@ -19,7 +19,7 @@
"dependencies": { "dependencies": {
"accepts": "^1.3.3", "accepts": "^1.3.3",
"debug": "^2.2.0", "debug": "^2.2.0",
"ejs": "^2.4.2", "ejs": "^2.5.7",
"http-status": "^1.0.0", "http-status": "^1.0.0",
"js2xmlparser": "^3.0.0", "js2xmlparser": "^3.0.0",
"strong-globalize": "^3.1.0" "strong-globalize": "^3.1.0"

View File

@ -472,6 +472,47 @@ describe('strong-error-handler', function() {
done); done);
}); });
it('HTML-escapes all 4xx response properties in production mode',
function(done) {
const error = new ErrorWithProps({
name: 'Error<img onerror=alert(1) src=a>',
message:
'No instance with id <img onerror=alert(1) src=a> found for Model',
statusCode: 404,
});
givenErrorHandlerForError(error, {debug: false});
requestHTML()
.end(function(err, res) {
expect(res.statusCode).to.eql(404);
const body = res.error.text;
expect(body).to.match(
/<title>Error&lt;img onerror=alert\(1\) src=a&gt;<\/title>/
);
expect(body).to.match(
/with id &lt;img onerror=alert\(1\) src=a&gt; found for Model/
);
done();
});
}
);
it('HTML-escapes all 5xx response properties in development mode',
function(done) {
const error = new ErrorWithProps({
message: 'a test error message<img onerror=alert(1) src=a>',
});
error.statusCode = 500;
givenErrorHandlerForError(error, {debug: true});
requestHTML()
.expect(500)
.expect(/<title>ErrorWithProps<\/title>/)
.expect(
/500(.*?)a test error message&lt;img onerror=alert\(1\) src=a&gt;/,
done
);
}
);
it('contains subset of properties when status=4xx', function(done) { it('contains subset of properties when status=4xx', function(done) {
var error = new ErrorWithProps({ var error = new ErrorWithProps({
name: 'ValidationError', name: 'ValidationError',

View File

@ -1,19 +1,19 @@
<html> <html>
<head> <head>
<meta charset='utf-8'> <meta charset='utf-8'>
<title><%- data.name || data.message %></title> <title><%= data.name || data.message %></title>
<style><%- include style.css %></style> <style><%- include style.css %></style>
</head> </head>
<body> <body>
<div id="wrapper"> <div id="wrapper">
<h1><%- data.name %></h1> <h1><%= data.name %></h1>
<h2><em><%- data.statusCode %></em> <%- data.message %></h2> <h2><em><%= data.statusCode %></em> <%= data.message %></h2>
<% <%
// display all the non-standard properties // display all the non-standard properties
var standardProps = ['name', 'statusCode', 'message', 'stack']; var standardProps = ['name', 'statusCode', 'message', 'stack'];
for (var prop in data) { for (var prop in data) {
if (standardProps.indexOf(prop) == -1 && data[prop]) { %> if (standardProps.indexOf(prop) == -1 && data[prop]) { %>
<div><b><%- prop %></b>: <%- data[prop] %></div> <div><b><%= prop %></b>: <%= data[prop] %></div>
<% } <% }
} }
if (data.stack) { %> if (data.stack) { %>