Summary
DOM.setFileInputFiles reads client-supplied local file paths from disk (std::fs::read) and hands their bytes (base64) to page JS — with no allow_file_access check. Any client that can reach the CDP port gets an arbitrary file-read primitive.
Location
crates/obscura-cdp/src/domains/dom.rs, setFileInputFiles handler:
for p in &paths {
let bytes = std::fs::read(p) // <-- no gate
.map_err(...)?;
...
}
The gap
Page.navigate to a file:// URL is already gated behind context.allow_file_access (default off; opt in via obscura serve --allow-file-access), precisely because "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". setFileInputFiles performs the same class of local-file read but skips that gate entirely.
Exploit
A CDP client sends DOM.setFileInputFiles targeting any <input type=file> with files: ["/etc/passwd"]; the file contents come back to page JS as a real File object it can read and exfiltrate. Especially impactful for deployments that bind the CDP port to 0.0.0.0.
Fix direction
Gate the handler behind page.context.allow_file_access, returning the same style of error as the navigate gate when it is off.
Severity
MEDIUM — arbitrary local file read, but requires CDP access and is off unless --allow-file-access is set (which then makes it intentional).
Summary
DOM.setFileInputFilesreads client-supplied local file paths from disk (std::fs::read) and hands their bytes (base64) to page JS — with noallow_file_accesscheck. Any client that can reach the CDP port gets an arbitrary file-read primitive.Location
crates/obscura-cdp/src/domains/dom.rs,setFileInputFileshandler:The gap
Page.navigateto afile://URL is already gated behindcontext.allow_file_access(default off; opt in viaobscura serve --allow-file-access), precisely because "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".setFileInputFilesperforms the same class of local-file read but skips that gate entirely.Exploit
A CDP client sends
DOM.setFileInputFilestargeting any<input type=file>withfiles: ["/etc/passwd"]; the file contents come back to page JS as a realFileobject it can read and exfiltrate. Especially impactful for deployments that bind the CDP port to0.0.0.0.Fix direction
Gate the handler behind
page.context.allow_file_access, returning the same style of error as the navigate gate when it is off.Severity
MEDIUM — arbitrary local file read, but requires CDP access and is off unless
--allow-file-accessis set (which then makes it intentional).