For those of you looking at this, I've found the X-Frame-Options (to prevent clickjacking via iframe) and Content-Security-Policy (to restrict eval, inline JS, JS and embed sources and more) to be the most useful headers by far. If you can run CSP without 'unsafe-eval' or 'unsafe-inline' and restrict all sources to your local domain, your site's security will be much better for it as an entire range of attacks is eliminated on modern browsers.
Of course they are all worth looking at. Scott's header test (https://securityheaders.io) is a great check for your own sites.
I wish some way existed to prevent clickjacking (e.g. via invisible iframe) without actually banning frames. There are useful applications for framing another site that can't be achieved by any other means, apart from writing a browser extension. And framing a site without making it invisible seems like unfortunate collateral damage.
A world with opt-in to unsafe behaviour would be great, but a long way off I fear. Thanks for mentioning the header check service!
But there is only so much you can do with headers, the real risks are in the documents themselves.
How about a <nojs> </nojs> pair in the primary document disabling any kind of javascript execution in the space between the tags. And those tags should only work in the primary document.
But wouldn't folks still be able to inject scripts by just writing `</nojs><script>alert('hi')</script><nojs>`?
app.use(lusca.csrf());
app.use(lusca.csp({ /* ... */}));
app.use(lusca.xframe('SAMEORIGIN'));
app.use(lusca.p3p('ABCDEF'));
app.use(lusca.hsts({ maxAge: 31536000 }));
app.use(lusca.xssProtection(true));
[1] https://github.com/krakenjs/luscaIt's free to sign up and use.
You can still use CSP, and whitelist specific third-party domains. (There's no way to whitelist inline code, though, and if there were it'd be more work than eliminating it and moving it to files.)
But the refactoring is well worth doing. By eliminating inline JavaScript and off-domain JavaScript, you eliminate the possibility of script injection. And directly including third-party JavaScript (or CSS, which can include JavaScript) opens you up to various kinds of attacks.
That's not completely true - the nonce attribute (specify a nonce in the CSP header, have nonce=that on every script tag) or by sending the hashes of the inline scripts upfront in the CSP header.
It doesn't give you inline code in attributes (e.g. onclick) but it's a big help for migrating.