Skip to content

Commit af01147

Browse files
committed
Don't break with INSTANT_MARKDOWN_ALLOW_UNSAFE_CONTENT=1
Previously the tight CSP would prevent the preview from working in Chrome because the stylesheets and WebSocket was blocked. And if unsafe content was allowed, then the variable to block external content did not work (INSTANT_MARKDOWN_BLOCK_EXTERNAL=1). Both issues have been fixed.
1 parent 36cbf0c commit af01147

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

instant-markdown-d

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,35 @@ function readAllInput(input, callback) {
5656
});
5757
}
5858

59-
function addSecurityHeaders(res, allowScriptsAtStartup) {
60-
if (process.env.INSTANT_MARKDOWN_ALLOW_UNSAFE_CONTENT) {
61-
return;
59+
function addSecurityHeaders(req, res, isIndexFile) {
60+
var csp = [];
61+
62+
// Cannot use 'self' because Chrome does not treat 'self' as http://host
63+
// when the sandbox directive is set.
64+
var HTTP_HOST = req.headers.host || 'localhost:8090';
65+
var CSP_SELF = 'http://' + HTTP_HOST;
66+
67+
if (!process.env.INSTANT_MARKDOWN_ALLOW_UNSAFE_CONTENT) {
68+
if (isIndexFile) {
69+
// index.html will drop the scripting capabilities upon load.
70+
csp.push('script-src ' + CSP_SELF + " 'unsafe-inline'");
71+
csp.push('sandbox allow-scripts allow-modals allow-forms');
72+
} else {
73+
csp.push('script-src ');
74+
}
6275
}
63-
64-
var csp =
65-
// index.html will drop the scripting capabilities upon load.
66-
"script-src " + (allowScriptsAtStartup ? "'self' 'unsafe-inline'": "") +
67-
"; sandbox allow-scripts allow-modals allow-forms";
6876
if (process.env.INSTANT_MARKDOWN_BLOCK_EXTERNAL) {
69-
csp += '; default-src "self"';
77+
csp.push('default-src data: ' + CSP_SELF);
78+
csp.push("style-src data: 'unsafe-inline' " + CSP_SELF);
79+
csp.push('connect-src ' + CSP_SELF + ' ws://' + HTTP_HOST);
7080
}
7181
res.setHeader('X-Content-Type-Options', 'nosniff');
72-
res.setHeader('Content-Security-Policy', csp);
82+
res.setHeader('Content-Security-Policy', csp.join('; '));
83+
if (isIndexFile) {
84+
// Never cache the index file, to make sure that changes to the CSP are
85+
// picked up across soft reloads.
86+
res.setHeader('Cache-Control', 'no-store');
87+
}
7388
}
7489

7590
function httpHandler(req, res) {
@@ -79,15 +94,16 @@ function httpHandler(req, res) {
7994
// Example: /my-repo/raw/master/sub-dir/some.png
8095
var githubUrl = req.url.match(/\/[^\/]+\/raw\/[^\/]+\/(.+)/);
8196
if (githubUrl) {
82-
addSecurityHeaders(res, false);
97+
addSecurityHeaders(req, res, false);
8398
// Serve the file out of the current working directory
8499
send(req, githubUrl[1])
85100
.root(process.cwd())
86101
.pipe(res);
87102
return;
88103
}
89104

90-
addSecurityHeaders(res, true);
105+
var isIndexFile = /^\/(index\.html)?(\?|$)/.test(req.url);
106+
addSecurityHeaders(req, res, isIndexFile);
91107

92108
// Otherwise serve the file from the directory this module is in
93109
send(req, req.url)

0 commit comments

Comments
 (0)