captchaforge 0.2.36

[DO NOT USE — UNDER ACTIVE DEVELOPMENT, NOT PRODUCTION-READY] Captcha solver scaffolding for chromiumoxide-driven browsers. The architecture is in place (vendor solvers, retry-loop iframe walking, VLM provider abstraction, real-WAF bench harness) but the live-vendor success rate is still 0% — Cloudflare Turnstile / hCaptcha / reCAPTCHA detect us at a TLS / CDP fingerprint layer that no flag-based stealth has cleared. Watch the repo; do not depend on this for any real workload.
Documentation
# Security Policy

## Reporting a Vulnerability

For security issues — anything that could let an attacker bypass
captchaforge's authentication / authorization / TLS hardening, leak
captured cookies, exfiltrate operator credentials, or inject
arbitrary code via a malicious rule pack — please **do not** open
a public GitHub issue.

Two accepted private channels — pick whichever you prefer:

1. **GitHub Security Advisory (preferred)** — go to
   <https://github.com/santhsecurity/captchaforge/security/advisories>
   and click **Report a vulnerability**. Fills a private draft
   GHSA visible only to the maintainers; comment threading + fix
   coordination + CVE issuance all happen inside the GHSA so
   nothing leaks to the public timeline until the patch ships.
2. **Email**`security@santh.dev`, subject
   `[captchaforge] <one-line summary>`. Use this when GitHub is
   down or you need to attach materials too large for a GHSA
   draft.

Either channel reaches the same on-call rotation.

We aim to:
- Acknowledge within 48 hours.
- Confirm + reproduce within 7 days.
- Ship a fix in the next patch release within 30 days.

For the report itself, please include:
- captchaforge version (`captchaforge --version` or the `version`
  field from your `Cargo.toml`).
- chromium version + OS.
- A minimal reproduction (a TOML rule pack, a synthesised page,
  or a network capture) that demonstrates the issue without
  pointing at any live victim.
- Your assessment of impact (information disclosure / RCE / DoS / …).

## Scope

In scope:
- The `captchaforge` crate (lib + cli + bench + challenge +
  rules-crate workspace members).
- The bundled `rules/community.toml` rule pack.
- The Python training scripts under `training/`.

Out of scope:
- The `chromiumoxide` / `tokio` / `reqwest` / `rustls` upstream
  dependencies — report those upstream.
- The `captchaforge-chromium` patched-binary fork (separate repo;
  has its own SECURITY.md).
- Issues in third-party CAPTCHA solving services (2captcha,
  CapSolver, CapMonster, …) called by the `ThirdPartyCaptchaSolver`
  — report those to the vendor.
- Vendor (Cloudflare / hCaptcha / reCAPTCHA / …) anti-bot
  countermeasures themselves — captchaforge solves visible
  captchas; if a vendor adds a new fingerprint surface that
  defeats stealth, that's a feature gap, not a security issue.

## Hardening Posture

The captchaforge codebase opts in to the following safety rails:

- `#![forbid(unsafe_code)]` on every shipped crate. No `unsafe`
  blocks; no `unsafe { ... }` blocks in the entire workspace.
- `cargo clippy --workspace --all-targets -- -D warnings` is
  CI-gated; no warnings ship.
- `cargo doc --workspace --no-deps` warning-free; broken
  intra-doc links fail CI.
- TOML rules are data-only — the rule-loading path
  (`captchaforge::detect::rules::RuleSet::parse`) never executes
  user-supplied JS or Rust. The probe JS the loader emits is
  generated from the rule's data via `serde_json::to_string`-
  escaped values; an attacker controlling a rule file cannot
  break out of the JS string context.
- Static rule validation: `captchaforge validate-rules` checks
  every TOML rule pack for selector parseability, priority
  collisions, and unknown solver_names. CI gates merges.
- Telemetry never logs full URLs / tokens / cookies — only
  domain + outcome + timing + per-vendor success rates. Operators
  wanting full request capture must opt into the
  `TrainingCorpus` pipeline, which warns about the
  privacy-sensitive payload in its docstring.
- The mouse-trace ingest server (`trace_ingest::TraceStore`)
  validates every payload against the realistic-trace envelope
  before persisting; payloads with sub-millisecond cadence,
  > 60s duration, < 3 steps, > 500 steps, or empty vendor
  field are rejected (401-class error in the future HTTP
  surface).

### HTTP boundary hardening (since 0.2.29)

- **Bounded response reads.** Every HTTP response captchaforge
  consumes is read through a max-bytes streaming cap so a hostile
  or buggy origin cannot OOM the worker by streaming an unbounded
  payload. `captchaforge::solver::token_oracle::TokenValidator`
  caps at 64 KiB; `captchaforge_challenge::capture_challenge`
  caps at 4 MiB. Overflow truncates rather than errors so
  classification still runs on the head.
- **Redirect policy.** The default `captchaforge_challenge`
  client allows at most 3 redirect hops and refuses any
  `https → non-https` downgrade. The previous reqwest default
  (10 hops, no scheme guard) was a hostile-redirect SSRF risk
  on challenge fetches.
- **SSRF defence on third-party config.** `Config::build_third_party_solver`
  no longer maps unrecognised `third_party.service` strings to
  a `Custom { base_url: ... }` solver. Only `service = "custom"`
  paired with an explicit `base_url` (which must parse as
  `http`/`https`) accepts a freeform endpoint; typos or untrusted
  config are rejected with a warning.
- **CORS default-deny.** `captchaforge serve` no longer wires
  `CorsLayer::permissive()` — cross-origin requests are blocked
  unless the operator explicitly passes `--allow-origin URL`
  (one or more times). Prevents browser-based CSRF-shaped abuse
  of POST `/solve` / `/detect` / `/transcribe` if the listener
  is ever bound beyond strict-localhost.
- **CF challenge success contract.** `captchaforge_challenge::cloudflare::CloudflareSolver`
  no longer returns `Ok(SolvedChallenge)` on any successful HTTP
  transport — it now requires a 2xx/3xx status AND the actual
  `cf_clearance` cookie, and uses the cookie's real Max-Age
  expiry rather than fabricating a 30-minute window. An optional
  `with_validated_revisions(&[...])` allowlist lets operators
  refuse PoW attempts against unrecognised CF revisions instead
  of silently producing wrong PoW answers.
- **JA4 spec compliance.** `captchaforge_challenge::ja3::compute_ja4`
  now follows the Foxio JA4 spec (sorted hex cipher/extension
  lists, real ALPN char extraction, server_name+ALPN excluded
  from the extension count, sigalgs joined after the extension
  hash). The previous bespoke simplification emitted strings
  that did not match real JA4 corpora or WAF dashboards.

## Supported Versions

The latest published `0.2.x` patch release is the only supported
line. Earlier `0.2.x` releases get security backports for 90 days
after their successor ships; older minor versions are not patched.
Pin to a major version (`captchaforge = "0.2"`) in production so
you receive security patches automatically without manual
intervention.