Fix dapps CSP when UI is exposed externally (#6178)
* Allow embeding on any page when ui-hosts=all and fix dev_ui * Fix tests.
This commit is contained in:
parent
ecd880c8e7
commit
65482c5e9d
@ -67,10 +67,20 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd
|
||||
// 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(),
|
||||
// Same restrictions as script-src (fallback) with additional
|
||||
{
|
||||
let script_src = embeddable_on.as_ref()
|
||||
.map(|e| e.extra_script_src.iter()
|
||||
.map(|&(ref host, port)| address(host, port))
|
||||
.join(" ")
|
||||
).unwrap_or_default();
|
||||
format!(
|
||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval' {};",
|
||||
script_src
|
||||
).into_bytes()
|
||||
},
|
||||
// Same restrictions as script-src with additional
|
||||
// blob: that is required for camera access (worker)
|
||||
b"worker-src 'self' 'unsafe-inline' 'unsafe-eval' blob: ;".to_vec(),
|
||||
b"worker-src 'self' 'unsafe-inline' 'unsafe-eval' https: blob:;".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)
|
||||
@ -90,7 +100,7 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd
|
||||
.into_iter()
|
||||
.chain(embed.extra_embed_on
|
||||
.iter()
|
||||
.map(|&(ref host, port)| format!("{}:{}", host, port))
|
||||
.map(|&(ref host, port)| address(host, port))
|
||||
);
|
||||
|
||||
let ancestors = if embed.host == "127.0.0.1" {
|
||||
|
@ -201,6 +201,7 @@ impl Middleware {
|
||||
remote: Remote,
|
||||
ui_address: Option<(String, u16)>,
|
||||
extra_embed_on: Vec<(String, u16)>,
|
||||
extra_script_src: Vec<(String, u16)>,
|
||||
dapps_path: PathBuf,
|
||||
extra_dapps: Vec<PathBuf>,
|
||||
dapps_domain: &str,
|
||||
@ -209,7 +210,7 @@ impl Middleware {
|
||||
web_proxy_tokens: Arc<WebProxyTokens>,
|
||||
fetch: F,
|
||||
) -> Self {
|
||||
let embeddable = as_embeddable(ui_address, extra_embed_on, dapps_domain);
|
||||
let embeddable = as_embeddable(ui_address, extra_embed_on, extra_script_src, dapps_domain);
|
||||
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
|
||||
hash_fetch::urlhint::URLHintContract::new(registrar),
|
||||
sync_status.clone(),
|
||||
@ -294,12 +295,14 @@ fn address(host: &str, port: u16) -> String {
|
||||
fn as_embeddable(
|
||||
ui_address: Option<(String, u16)>,
|
||||
extra_embed_on: Vec<(String, u16)>,
|
||||
extra_script_src: Vec<(String, u16)>,
|
||||
dapps_domain: &str,
|
||||
) -> Option<ParentFrameSettings> {
|
||||
ui_address.map(|(host, port)| ParentFrameSettings {
|
||||
host,
|
||||
port,
|
||||
extra_embed_on,
|
||||
extra_script_src,
|
||||
dapps_domain: dapps_domain.to_owned(),
|
||||
})
|
||||
}
|
||||
@ -320,8 +323,10 @@ pub struct ParentFrameSettings {
|
||||
pub host: String,
|
||||
/// Port
|
||||
pub port: u16,
|
||||
/// Additional pages the pages can be embedded on.
|
||||
/// Additional URLs the dapps can be embedded on.
|
||||
pub extra_embed_on: Vec<(String, u16)>,
|
||||
/// Additional URLs the dapp scripts can be loaded from.
|
||||
pub extra_script_src: Vec<(String, u16)>,
|
||||
/// Dapps Domain (web3.site)
|
||||
pub dapps_domain: String,
|
||||
}
|
||||
|
@ -260,6 +260,7 @@ impl Server {
|
||||
remote,
|
||||
signer_address,
|
||||
vec![],
|
||||
vec![],
|
||||
dapps_path,
|
||||
extra_dapps,
|
||||
DAPPS_DOMAIN.into(),
|
||||
|
@ -20,6 +20,7 @@ use std::net::SocketAddr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::collections::BTreeMap;
|
||||
use std::cmp::max;
|
||||
use std::str::FromStr;
|
||||
use cli::{Args, ArgsError};
|
||||
use util::{Hashable, H256, U256, Bytes, version_data, Address};
|
||||
use util::journaldb::Algorithm;
|
||||
@ -551,6 +552,10 @@ impl Configuration {
|
||||
Ok(options)
|
||||
}
|
||||
|
||||
fn ui_port(&self) -> u16 {
|
||||
self.args.flag_ports_shift + self.args.flag_ui_port
|
||||
}
|
||||
|
||||
fn ntp_servers(&self) -> Vec<String> {
|
||||
self.args.flag_ntp_servers.split(",").map(str::to_owned).collect()
|
||||
}
|
||||
@ -560,12 +565,15 @@ impl Configuration {
|
||||
enabled: self.ui_enabled(),
|
||||
ntp_servers: self.ntp_servers(),
|
||||
interface: self.ui_interface(),
|
||||
port: self.args.flag_ports_shift + self.args.flag_ui_port,
|
||||
port: self.ui_port(),
|
||||
hosts: self.ui_hosts(),
|
||||
}
|
||||
}
|
||||
|
||||
fn dapps_config(&self) -> DappsConfiguration {
|
||||
let dev_ui = if self.args.flag_ui_no_validation { vec![("localhost".to_owned(), 3000)] } else { vec![] };
|
||||
let ui_port = self.ui_port();
|
||||
|
||||
DappsConfiguration {
|
||||
enabled: self.dapps_enabled(),
|
||||
ntp_servers: self.ntp_servers(),
|
||||
@ -575,11 +583,26 @@ impl Configuration {
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
extra_embed_on: if self.args.flag_ui_no_validation {
|
||||
vec![("localhost".to_owned(), 3000)]
|
||||
} else {
|
||||
vec![]
|
||||
extra_embed_on: {
|
||||
let mut extra_embed = dev_ui.clone();
|
||||
match self.ui_hosts() {
|
||||
// In case host validation is disabled allow all frame ancestors
|
||||
None => extra_embed.push(("*".to_owned(), ui_port)),
|
||||
Some(hosts) => extra_embed.extend(hosts.into_iter().filter_map(|host| {
|
||||
let mut it = host.split(":");
|
||||
let host = it.next();
|
||||
let port = it.next().and_then(|v| u16::from_str(v).ok());
|
||||
|
||||
match (host, port) {
|
||||
(Some(host), Some(port)) => Some((host.into(), port)),
|
||||
(Some(host), None) => Some((host.into(), ui_port)),
|
||||
_ => None,
|
||||
}
|
||||
})),
|
||||
}
|
||||
extra_embed
|
||||
},
|
||||
extra_script_src: dev_ui,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ pub struct Configuration {
|
||||
pub dapps_path: PathBuf,
|
||||
pub extra_dapps: Vec<PathBuf>,
|
||||
pub extra_embed_on: Vec<(String, u16)>,
|
||||
pub extra_script_src: Vec<(String, u16)>,
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
@ -56,6 +57,7 @@ impl Default for Configuration {
|
||||
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
||||
extra_dapps: vec![],
|
||||
extra_embed_on: vec![],
|
||||
extra_script_src: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -168,6 +170,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Mi
|
||||
configuration.extra_dapps,
|
||||
rpc::DAPPS_DOMAIN,
|
||||
configuration.extra_embed_on,
|
||||
configuration.extra_script_src,
|
||||
).map(Some)
|
||||
}
|
||||
|
||||
@ -214,6 +217,7 @@ mod server {
|
||||
_extra_dapps: Vec<PathBuf>,
|
||||
_dapps_domain: &str,
|
||||
_extra_embed_on: Vec<(String, u16)>,
|
||||
_extra_script_src: Vec<(String, u16)>,
|
||||
) -> Result<Middleware, String> {
|
||||
Err("Your Parity version has been compiled without WebApps support.".into())
|
||||
}
|
||||
@ -251,6 +255,7 @@ mod server {
|
||||
extra_dapps: Vec<PathBuf>,
|
||||
dapps_domain: &str,
|
||||
extra_embed_on: Vec<(String, u16)>,
|
||||
extra_script_src: Vec<(String, u16)>,
|
||||
) -> Result<Middleware, String> {
|
||||
let signer = deps.signer;
|
||||
let parity_remote = parity_reactor::Remote::new(deps.remote.clone());
|
||||
@ -262,6 +267,7 @@ mod server {
|
||||
parity_remote,
|
||||
deps.ui_address,
|
||||
extra_embed_on,
|
||||
extra_script_src,
|
||||
dapps_path,
|
||||
extra_dapps,
|
||||
dapps_domain,
|
||||
|
Loading…
Reference in New Issue
Block a user