Content Security Policy (#5790)
* Adding CSP headers. * Adding Content-Security-Policy headers. * Fixing test. * CSP in ws server responses.
This commit is contained in:
parent
57626b60e7
commit
c7a043b864
@ -38,15 +38,53 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Option
|
|||||||
headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
|
headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]);
|
||||||
|
|
||||||
// Embedding header:
|
// Embedding header:
|
||||||
if let Some(embeddable_on) = embeddable_on {
|
if let Some(ref embeddable_on) = embeddable_on {
|
||||||
headers.set_raw(
|
headers.set_raw("X-Frame-Options", vec![
|
||||||
"X-Frame-Options",
|
format!("ALLOW-FROM http://{}", address(embeddable_on)).into_bytes()
|
||||||
vec![format!("ALLOW-FROM http://{}", address(&embeddable_on)).into_bytes()]
|
]);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
// TODO [ToDr] Should we be more strict here (DENY?)?
|
// TODO [ToDr] Should we be more strict here (DENY?)?
|
||||||
headers.set_raw("X-Frame-Options", vec![b"SAMEORIGIN".to_vec()]);
|
headers.set_raw("X-Frame-Options", vec![b"SAMEORIGIN".to_vec()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Content Security Policy headers
|
||||||
|
headers.set_raw("Content-Security-Policy", vec![
|
||||||
|
// Allow connecting to WS servers and HTTP(S) servers.
|
||||||
|
// We could be more restrictive and allow only RPC server URL.
|
||||||
|
b"connect-src http: https: ws: wss:;".to_vec(),
|
||||||
|
// Allow framing any content from HTTP(S).
|
||||||
|
// Again we could only allow embedding from RPC server URL.
|
||||||
|
// (deprecated)
|
||||||
|
b"frame-src 'self' http: https:;".to_vec(),
|
||||||
|
// Allow framing and web workers from HTTP(S).
|
||||||
|
b"child-src 'self' http: https:;".to_vec(),
|
||||||
|
// We allow data: blob: and HTTP(s) images.
|
||||||
|
// We could get rid of wildcarding HTTP and only allow RPC server URL.
|
||||||
|
// (http require for local dapps icons)
|
||||||
|
b"img-src 'self' 'unsafe-inline' data: blob: http: https:;".to_vec(),
|
||||||
|
// Allow style from data: blob: and HTTPS.
|
||||||
|
b"style-src 'self' 'unsafe-inline' data: blob: https:;".to_vec(),
|
||||||
|
// Allow fonts from data: and HTTPS.
|
||||||
|
b"font-src 'self' data: https:;".to_vec(),
|
||||||
|
// Allow inline scripts and scripts eval (webpack/jsconsole)
|
||||||
|
b"script-src 'self' 'unsafe-inline' 'unsafe-eval';".to_vec(),
|
||||||
|
// Restrict everything else to the same origin.
|
||||||
|
b"default-src 'self';".to_vec(),
|
||||||
|
// Run in sandbox mode (although it's not fully safe since we allow same-origin and script)
|
||||||
|
b"sandbox allow-same-origin allow-forms allow-modals allow-popups allow-presentation allow-scripts;".to_vec(),
|
||||||
|
// Disallow subitting forms from any dapps
|
||||||
|
b"form-action 'none';".to_vec(),
|
||||||
|
// Never allow mixed content
|
||||||
|
b"block-all-mixed-content;".to_vec(),
|
||||||
|
// Specify if the site can be embedded.
|
||||||
|
match embeddable_on {
|
||||||
|
Some((ref host, ref port)) if host == "127.0.0.1" => {
|
||||||
|
format!("frame-ancestors {} {};", address(&(host.to_owned(), *port)), address(&("localhost".to_owned(), *port)))
|
||||||
|
},
|
||||||
|
Some(ref embed) => format!("frame-ancestors {};", address(embed)),
|
||||||
|
None => format!("frame-ancestors 'self';"),
|
||||||
|
}.into_bytes(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,4 +121,8 @@ pub fn assert_security_headers_present(headers: &[String], port: Option<u16>) {
|
|||||||
headers.iter().find(|header| header.as_str() == "X-Content-Type-Options: nosniff").is_some(),
|
headers.iter().find(|header| header.as_str() == "X-Content-Type-Options: nosniff").is_some(),
|
||||||
"X-Content-Type-Options missing: {:?}", headers
|
"X-Content-Type-Options missing: {:?}", headers
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
headers.iter().find(|header| header.starts_with("Content-Security-Policy: ")).is_some(),
|
||||||
|
"Content-Security-Policy missing: {:?}", headers
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ export default class DappIcon extends Component {
|
|||||||
src={
|
src={
|
||||||
app.type === 'local'
|
app.type === 'local'
|
||||||
? `${dappsUrl}/${app.id}/${app.iconUrl}`
|
? `${dappsUrl}/${app.id}/${app.iconUrl}`
|
||||||
: `${dappsUrl}${app.image}`
|
: `${app.image}`
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -64,7 +64,7 @@ describe('ui/DappIcon', () => {
|
|||||||
|
|
||||||
it('renders other apps with correct URL', () => {
|
it('renders other apps with correct URL', () => {
|
||||||
expect(render({ app: { id: 'test', image: '/test.img' } }).props().src).to.equal(
|
expect(render({ app: { id: 'test', image: '/test.img' } }).props().src).to.equal(
|
||||||
`${DAPPS_URL}/test.img`
|
`/test.img`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -140,6 +140,9 @@ fn add_security_headers(res: &mut ws::ws::Response) {
|
|||||||
headers.push(("X-Frame-Options".into(), b"SAMEORIGIN".to_vec()));
|
headers.push(("X-Frame-Options".into(), b"SAMEORIGIN".to_vec()));
|
||||||
headers.push(("X-XSS-Protection".into(), b"1; mode=block".to_vec()));
|
headers.push(("X-XSS-Protection".into(), b"1; mode=block".to_vec()));
|
||||||
headers.push(("X-Content-Type-Options".into(), b"nosniff".to_vec()));
|
headers.push(("X-Content-Type-Options".into(), b"nosniff".to_vec()));
|
||||||
|
headers.push(("Content-Security-Policy".into(),
|
||||||
|
b"default-src 'self';form-action 'none';block-all-mixed-content;sandbox allow-scripts;".to_vec()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auth_token_hash(codes_path: &Path, protocol: &str, save_file: bool) -> Option<H256> {
|
fn auth_token_hash(codes_path: &Path, protocol: &str, save_file: bool) -> Option<H256> {
|
||||||
|
Loading…
Reference in New Issue
Block a user