Files
obscura/Cargo.toml
Andrey Mnatsakanov e5904a6ee2 fix(render): apply the SSRF deny-set to the renderer's standalone HTTP loader
The render crate's compatibility loader (a pooled ureq agent behind
RenderResourceCache::default) fetched images and fonts with no network
policy at all. A page-owned runtime never uses it (it is cache-only and
fetches through obscura-net), but every standalone caller did: the
paint_file tool, library users rendering a bare DOM, and a JS runtime
with no page transport. Markup referencing http://127.0.0.1/,
http://169.254.169.254/ or a hostname that resolves to a private address
made the renderer connect to it.

Move is_forbidden_ip and env_allows_private_network into a new
zero-dependency obscura-ssrf crate so obscura-net and obscura-render
enforce one deny-set (obscura-net re-exports both, so its API and the
wreq transport are unchanged). Install a ureq resolver on the render
agent that rejects any resolved address in the deny-set unless
OBSCURA_ALLOW_PRIVATE_NETWORK is set, which covers literal addresses,
DNS rebinding, and every redirect hop. A resolver refusal surfaces as a
DNS transport error; the retry loop now returns immediately on those
instead of sleeping through 600ms of backoff for a request it will not
make.
2026-09-27 12:48:25 +02:00

81 lines
2.7 KiB
TOML

[workspace]
resolver = "2"
members = [
"crates/obscura-dom",
"crates/obscura-ssrf",
"crates/obscura-net",
"crates/obscura-browser",
"crates/obscura-cdp",
"crates/obscura-js",
"crates/obscura-mcp",
"crates/obscura-render",
"crates/obscura-cli",
"crates/obscura",
]
[workspace.package]
version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/h4ckf0r0day/obscura"
[workspace.dependencies]
obscura-dom = { path = "crates/obscura-dom" }
obscura-ssrf = { path = "crates/obscura-ssrf" }
obscura-net = { path = "crates/obscura-net" }
obscura-browser = { path = "crates/obscura-browser" }
obscura-cdp = { path = "crates/obscura-cdp" }
obscura-js = { path = "crates/obscura-js" }
obscura-mcp = { path = "crates/obscura-mcp" }
obscura-render = { path = "crates/obscura-render" }
html5ever = "0.39"
markup5ever = "0.39"
selectors = "0.26"
servo_arc = "0.4"
cssparser = "0.34"
# Layout engine for the optional render layer (obscura-render). Pure Rust.
taffy = "0.12"
# CPU-only pure-Rust 2D rasterizer for the render layer's paint step.
tiny-skia = "0.12"
# Pure-Rust glyph rasterizer for the render layer's text step.
ab_glyph = "0.2"
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.26"
# No "cookies" feature: obscura manages cookies through its own CookieJar
# (obscura-net/src/cookies.rs) and never uses reqwest's cookie store. Pulling
# it in only added the cookie/cookie_store crates, and cookie 0.18.1's blanket
# From impl fails to compile under coherence on some toolchains (issue #295).
reqwest = { version = "0.12", features = ["gzip", "brotli", "deflate", "rustls-tls", "socks"], default-features = false }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
url = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
clap = { version = "4", features = ["derive"] }
uuid = { version = "1", features = ["v4"] }
thiserror = "2"
anyhow = "1"
base64 = "0.22"
[patch.crates-io]
# Keep the grid shrink-to-fit correction local until it lands upstream.
taffy = { path = "vendor/taffy" }
# Carry the same canonical variable-font coordinates through shaping and
# rasterization until the upstream API exposes them.
cosmic-text = { path = "vendor/cosmic-text" }
# Unwinding (the Rust default) is REQUIRED for the anti-panic protocol: ops wrap
# their bodies in std::panic::catch_unwind so a panic degrades to an error return
# instead of unwinding into V8's FFI frame and aborting the process. panic="abort"
# would turn every catchable op panic into a hard crash.
[profile.release]
panic = "unwind"
[profile.release-dist]
inherits = "release"
opt-level = "s"
lto = "fat"
codegen-units = 1
strip = "symbols"