Skip to content

v0.7.7 — GAP-WS-49 fix: TLS fingerprint emulation restored

Latest

Choose a tag to compare

@daniloaguiarbr daniloaguiarbr released this 14 Jun 10:36
· 1 commit to main since this release

duckduckgo-search-cli v0.7.7

GAP-WS-49 (CRITICAL, runtime) — v0.7.6 closed cargo install but real queries returned ZERO results silently. This patch restores the Chrome/Safari TLS fingerprint emulation that bypasses DDG's anomaly-modal.

What's new in v0.7.7

Critical runtime fix (GAP-WS-49)

  • Zero-result regression fixed. v0.7.6 passed all --probe and --probe-deep smoke tests (status 200/ok) while real queries silently returned resultados: 0 with cascade_level: 0 and usou_endpoint_fallback: false. Local reproduction: 6/6 queries returned 0 results with 1.0–1.6s latency.
  • Root cause: wreq 6.0.0-rc.29 does not bundle the emulation feature. The Chrome/Safari TLS fingerprint emulation lived only in wreq-util 3.0.0-rc.12 via default = ["emulation"]. v0.7.6 removed wreq-util (along with the brotli feature) to close GAP-WS-48, and without emulation, wreq 6.0.0-rc.29 with BoringSSL plain produces a JA3/JA4 fingerprint that Cloudflare Bot Management detects. DDG serves anomaly-modal HTML (45 occurrences) to any client without a real browser fingerprint.
  • Cross-confirmation: curl with real browser headers (User-Agent: Chrome/120, Accept-Encoding: br, Sec-Fetch-*) also received anomaly-modal at test time (2026-06-14 09:25 UTC), confirming the upstream tightening.
  • Fix:
    1. Re-added wreq-util 3.0.0-rc.12 with default-features = false, features = ["emulation"].
    2. Re-added "brotli" feature to wreq (required by emulation).
    3. Added 3 direct dep pins to Cargo.toml to force compatible versions in cargo install:
      • brotli-decompressor = "=5.0.1" — last version with hard alloc-no-stdlib = "2.0" pin, before 5.0.2 widened to >=2.0.4, <4.
      • alloc-no-stdlib = "=2.0.4" — exact version brotli 8.0.3 hard-requires.
      • brotli = { version = "8.0.3", default-features = false } — no std feature, doesn't pull alloc-stdlib 0.2.3.
    4. cargo update -p alloc-no-stdlib@3.0.0 --precise 2.0.4 removes 3.0.0 from the lockfile.
  • Post-fix validation:
    • cargo tree --offline — graph contains exactly alloc-no-stdlib v2.0.4 and brotli-decompressor v5.0.1, zero 3.0.0/0.2.3.
    • cargo build --release --offline — success in 24.04s.
    • cargo install --path . --locked --offline — success in 34.32s, binary functional.
    • 292 lib tests pass.
    • Real query "rust async runtime" (local) — quantidade_resultados: 5, latency 1087ms, real results.

⚠️ GAP-WS-48 residual: cargo install without --locked still fails

Because cargo install regenerates the lockfile, the solver adds BOTH alloc-no-stdlib 2.0.4 (from the direct pin) and alloc-no-stdlib 3.0.0 (from brotli-decompressor 5.0.2 or transitive alloc-stdlib 0.2.3). This triggers the same E0277 as GAP-WS-48. Users must use --locked:

cargo install duckduckgo-search-cli --version 0.7.7 --locked

The committed Cargo.lock was prepared with cargo update -p alloc-no-stdlib@3.0.0 --precise 2.0.4 to make --locked produce a clean graph.

Impact

  • Binary: +160KB (brotli 8.0.3 + brotli-decompressor 5.0.1 + wreq-util 3.0.0-rc.12).
  • cargo install build time: ~24s (vs ~37s v0.7.6).
  • Supply chain surface: +3 crates.
  • Functionality restored: real queries return 5+ results with a TLS fingerprint identical to real Chrome/Safari (subject to DDG's tightening state).

Install

cargo install duckduckgo-search-cli --version 0.7.7 --locked

What's NOT changed

  • No CLI changes
  • No JSON schema changes
  • No skill file semantic changes (only version bump + GAP-WS-49 documentation)

Verification

  • cargo build --release --offline — success in 24.04s
  • cargo install --path . --locked --offline — success in 34.32s
  • cargo test --lib --offline — 292 passed; 0 failed
  • cargo fmt --check — clean
  • cargo clippy --all-targets --offline -- -D warnings — clean
  • Query test (local): quantidade_resultados: 5, real results

See CHANGELOG.md for the full GAP-WS-49 narrative.