#995·obscura

--stealth unconditionally enables the tracker blocklist; ObscuraHttpClient gates it, StealthHttpClient does not

Author: prinfraCreated Sep 15, 2026Updated Sep 15, 2026

Summary

--stealth also turns on the bundled tracker blocklist, and there is no way to turn it off. The two HTTP transports disagree:

  • ObscuraHttpClient gates the check behind a field (client.rs):
    rust
    pub block_trackers: bool,   // initialised to false
    ...
    if self.block_trackers {
        if let Some(host) = url.host_str() {
            if crate::blocklist::is_blocked(host) { ... }
  • StealthHttpClient has no such field and checks unconditionally, in two places (wreq_client.rs):
    rust
    if let Some(host) = current_url.host_str() {
        if crate::blocklist::is_blocked(host) { ... }

So the documented stealth behaviour ("TLS impersonation plus tracker blocking") is really "TLS impersonation, and tracker blocking whether you want it or not".

Why it matters

Blocking trackers is a sensible default for agent browsing and the wrong one for observing a page as it actually loads. Measuring a site's third-party stack, auditing what a page contacts, or reproducing a bug that only occurs with analytics present all need the blocklist off, and stealth TLS on, at the same time. Today those two are welded together.

On https://www.hubspot.com/ the blocklist drops 8 requests. Because one of them is the consent bundle that injects Google Tag Manager, the whole downstream tag cascade never loads.

Suggested fix

Give StealthHttpClient the same field ObscuraHttpClient already has, and gate both call sites on it. Default it to true so --stealth behaves exactly as documented, and read an env override so it can be switched off:

rust
pub struct StealthHttpClient {
    ...
    pub block_trackers: bool,
}

fn block_trackers_from_env() -> bool {
    match std::env::var("OBSCURA_BLOCK_TRACKERS") {
        Ok(v) => !matches!(v.trim().to_ascii_lowercase().as_str(), "0" | "false" | "no" | "off"),
        Err(_) => true,
    }
}

then if self.block_trackers && crate::blocklist::is_blocked(host) at both sites. Verified: blocked-request count on hubspot.com goes from 4 to 1 with OBSCURA_BLOCK_TRACKERS=0 (the remaining one comes from the non-stealth transport, which has its own flag).

A CLI flag such as --no-block-trackers would be friendlier than an env var if you'd prefer that shape; the env var was the smallest change that also works for serve.

Environment

  • obscura 0.2.2, main @ 4b70288
  • built --release -p obscura-cli --bins --features render,stealth
  • Ubuntu 24.04, x86_64

Tests

cargo test --release -p obscura-net --features stealth gives 102 passed / 3 failed both with and without this change — the same three fail on a clean main checkout here, so they look unrelated: ssrf_tests::configured_roots_trust_a_private_ca_via_ssl_cert_{dir,file} and wreq_client::tests::stealth_client_decodes_gzip_response.