fix(cdp): gate file:// navigation behind --allow-file-access
GHSA-q55h-vfv9-qcr5. Any process able to reach the CDP port could
send Page.navigate {"url":"file:///etc/shadow"} and read arbitrary
local files (the process's UID's worth of read access). When obscura
runs as root inside Docker or as a systemd service that translates
straight into /etc/shadow, /root/.ssh/id_rsa, /proc/1/environ, etc.
Validate at the CDP boundary, not in obscura-net, so direct CLI
callers ("obscura fetch file://...") keep working. A new
BrowserContext.allow_file_access flag defaults to false; Page.navigate
returns an error when the requested URL is file:// and the flag is
off. CdpContext::new_with_security threads the flag from the server
entry point, and "obscura serve --allow-file-access" opts in for
local-HTML testing workflows.
Tested:
- Default obscura serve: CDP Page.navigate {file:///etc/passwd} ->
refused with descriptive error.
- obscura serve --allow-file-access: same call succeeds.
- obscura fetch file://... CLI path: unchanged, still reads the file.
- All earlier PoCs (GHSA-6pj9 JS->file SOP, GHSA-4789 sub-resource
SSRF, GHSA-4789 CSS template injection) still pass.
- cargo test --workspace clean.
This commit is contained in:
1 parent
ac0efd1798
commit
18dc796df0
6 files changed
+75
-7
No files matched your search
@@ -53,6 +53,13 @@ enum Command {
|
||||
|
||||
#[arg(long, default_value_t = 1)]
|
||||
workers: u16,
|
||||
|
||||
/// Allow CDP clients to navigate to file:// URLs. Off by
|
||||
/// default so a CDP connection cannot read arbitrary local
|
||||
/// files. Enable only when serving local HTML for testing
|
||||
/// and the port is on a trusted network.
|
||||
#[arg(long)]
|
||||
allow_file_access: bool,
|
||||
},
|
||||
|
||||
Fetch {
|
||||
@@ -192,7 +199,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
let global_proxy = args.proxy.clone();
|
||||
|
||||
match args.command {
|
||||
Some(Command::Serve { port, host, proxy, user_agent, stealth, workers }) => {
|
||||
Some(Command::Serve { port, host, proxy, user_agent, stealth, workers, allow_file_access }) => {
|
||||
let proxy = merge_proxy(global_proxy.clone(), proxy);
|
||||
print_banner(port);
|
||||
if let Some(ref proxy) = proxy {
|
||||
@@ -214,7 +221,9 @@ async fn main() -> anyhow::Result<()> {
|
||||
tracing::info!("{} worker processes", workers);
|
||||
run_multi_worker_serve(port, workers, proxy, stealth, user_agent).await?;
|
||||
} else {
|
||||
obscura_cdp::start_with_host(port, &host, proxy, stealth, user_agent).await?;
|
||||
obscura_cdp::start_with_host_and_security(
|
||||
port, &host, proxy, stealth, user_agent, allow_file_access,
|
||||
).await?;
|
||||
}
|
||||
}
|
||||
Some(Command::Fetch { url, dump, selector, wait, timeout, wait_until, user_agent, stealth, eval, output, quiet }) => {
|
||||
|
||||
Reference in new issue
Block a user