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
@@ -4,6 +4,14 @@ use serde_json::{json, Value};
|
||||
use crate::dispatch::CdpContext;
|
||||
use crate::types::CdpEvent;
|
||||
|
||||
fn url_is_file_scheme(raw: &str) -> bool {
|
||||
url::Url::parse(raw)
|
||||
.map(|u| u.scheme().eq_ignore_ascii_case("file"))
|
||||
.unwrap_or_else(|_| {
|
||||
raw.trim_start().to_ascii_lowercase().starts_with("file:")
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn handle(
|
||||
method: &str,
|
||||
params: &Value,
|
||||
@@ -16,6 +24,18 @@ pub async fn handle(
|
||||
let url = params.get("url").and_then(|v| v.as_str())
|
||||
.ok_or("url required")?;
|
||||
|
||||
// Block CDP-initiated file:// navigation by default.
|
||||
// Anyone who can reach the CDP port (default localhost,
|
||||
// but Docker images bind 0.0.0.0) could otherwise read
|
||||
// any file the obscura process can read. Opt in via
|
||||
// `obscura serve --allow-file-access` when local-HTML
|
||||
// testing is the intended workflow.
|
||||
if url_is_file_scheme(url) && !ctx.default_context.allow_file_access {
|
||||
return Err(
|
||||
"Page.navigate to file:// is disabled. Restart with `obscura serve --allow-file-access` to enable.".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
let wait_until = params.get("waitUntil")
|
||||
.and_then(|v| {
|
||||
if let Some(s) = v.as_str() {
|
||||
|
||||
Reference in new issue
Block a user