Spike Scout Edge Interop
Spike: Cloudflare Edge Interoperability & Bot Challenge Bypass for Synthetic QA Scouts
Executive Summary: This architectural spike investigates edge security interoperability to permit automated local browser scouts (Epic #762) to reliably test Cloudflare-hosted staging and preview deployments without triggering Cloudflare Bot Management, Turnstile challenges, or WAF rate limits. We specify and validate an HMAC-SHA256 signed request header protocol with strict replay protection ($\le$ 300s TTL), Cloudflare Turnstile dummy testing credential orchestration, and a hard negative production lockdown invariant that guarantees zero weakening of production security postures.
1. Context & Problem Statement
1.1 Epic #762 Scope & The Residential Scout Challenge
SiteSwarm’s synthetic QA scout platform runs autonomous local-model agents driving real headless Chromium browsers to validate staging and preview deployments across client applications. Unlike static synthetic probes originating from fixed data center CIDR blocks, synthetic scouts run on developer workstations, residential broadband connections, and distributed local runners.
When these browser sessions interact with Cloudflare-fronted staging environments, they encounter multiple layers of edge security designed to detect and block automated traffic:
- Cloudflare Bot Management & Super Bot Fight Mode (SBFM): Analyzes TLS client handshakes (JA3/JA4 fingerprints), HTTP/2 frame parameters, TCP window sizes, browser canvas/audio fingerprint heuristics, and headless automation attributes (e.g.
navigator.webdriver, missing browser plugins). - Cloudflare Turnstile Challenges: Interactive or non-interactive CAPTCHA widgets placed on inquiry forms, newsletter signups, and admin portals that stall or fail headless automated browser sessions.
- Cloudflare WAF Custom & Rate Limiting Rules: Aggressive request rate limits that throttle high-frequency synthetic user exploratory journeys.
1.2 Spike Research Questions (#768)
- The Unknown Question: What is the most secure, maintainable mechanism to allow automated local browser scouts to test Cloudflare-hosted staging and preview deployments without triggering Cloudflare Bot Management or Turnstile challenges, while preserving production security postures?
- Decision Blocked: Edge security rule configuration, scout request authentication headers, and staging Turnstile bypass strategy.
- Hard Negative Constraint: No predetermined security approach. Do NOT whitelist all headless User-Agents or disable WAF entirely on staging. Bypass rules must be strictly scoped to preview/staging hostnames with cryptographic authentication.
2. Threat Modeling & Failure-Mode Analysis
| Threat / Anti-Pattern | Attack Vector / Risk | Architectural Mitigation in #768 |
|---|---|---|
| Insecure Global UA Whitelist | Attacker spoofing User-Agent: SiteSwarm-Scout/1.0 bypasses all security. |
Rejected: User-Agent headers are never used as authentication tokens. Cryptographic HMAC-SHA256 signature required. |
| Static Cleartext Shared Secret | Static header value (e.g. X-Bypass: my-secret) leaked in client bundles or network logs. |
Rejected: Shared secret is never transmitted. Signatures are one-way HMAC-SHA256 digests over a canonical request payload. |
| Signature Replay Attack | Malicious actor captures valid signed request and replays it indefinitely against staging. | Mitigated: Canonical string embeds UNIX timestamp; edge verifier strictly rejects requests with age $>300$ seconds or clock skew $>60$ seconds. |
| Cross-Method Privilege Escalation | Signature generated for safe GET /menu replayed as destructive POST /api/inquiries. |
Mitigated: HTTP method and full request path/query are baked into the canonical signature preimage. |
| Production Apex Leakage | Bypass rule or test credentials mistakenly applied to production domains (jacobmiller22.com). |
Mitigated: Edge verifier and browser signer enforce a Hard Negative Guardrail: requests to production hostnames are unconditionally rejected (HTTP 403). |
| Turnstile Widget Stalling | Interactive Turnstile challenge on form submission blocks headless scout runner. | Mitigated: Dual-layer staging bypass: Cloudflare official dummy test keys (1x00000000000000000000AA) + Playwright DOM auto-fill helper. |
3. Cryptographic Bypass Protocol Specification
3.1 Header Schema
Every outbound HTTP request initiated by a synthetic scout browser context is dynamically injected with three authentication headers:
X-Synthetic-Scout-Signature: 8f4a7c1b3e9d2a6... (64-character lowercase hex string)X-Synthetic-Scout-Timestamp: 1773000500 (UNIX timestamp in integer seconds)X-Synthetic-Scout-Key-Id: scout-v1 (Key identifier string for rotation)3.2 Canonical Preimage Format
The signature is generated as HMAC-SHA256(canonicalString, secret). The canonical string format is strictly normalized as:
${METHOD}\n${HOST}\n${PATH_AND_QUERY}\n${TIMESTAMP}\n${KEY_ID}Preimage Normalization Invariants:
- Method: Normalized to uppercase (
GET,POST,PUT,DELETE,PATCH,HEAD). - Host: Normalized to lowercase, including non-standard port if present (e.g.
bakery-staging.jacobmiller22.comorlocalhost:8787). - Path and Query: Normalized to ensure leading slash
/, preserving exact query parameter string (e.g./api/menu?category=pastries). - Timestamp: ASCII integer string representing UTC epoch seconds.
- Key-ID: ASCII identifier string matching registered edge secret (default:
scout-v1).
// Canonical string construction exampleexport function buildCanonicalScoutString(params: { method: string; host: string; pathnameAndSearch: string; timestamp: number | string; keyId?: string;}): string { const method = params.method.trim().toUpperCase(); const host = params.host.trim().toLowerCase(); let path = params.pathnameAndSearch.trim(); if (!path.startsWith('/')) path = `/${path}`; const timestamp = String(params.timestamp).trim(); const keyId = (params.keyId || 'scout-v1').trim();
return `${method}\n${host}\n${path}\n${timestamp}\n${keyId}`;}3.3 Replay Protection & Validity Windows
- Maximum Permitted Age (
maxAgeSeconds):300seconds (5 minutes). Requests wherenow - timestamp > 300fail closed withTIMESTAMP_EXPIRED. - Clock Skew Tolerance (
maxClockSkewSeconds):60seconds. Requests wheretimestamp - now > 60fail closed withTIMESTAMP_FUTURE_SKEW. - Constant-Time Verification: Verification evaluates
crypto.timingSafeEqualbetween expected and received signature digests to prevent side-channel timing attacks.
4. Staging Turnstile Testing Strategy
Cloudflare Turnstile provides official dummy test sitekeys and secret keys designed specifically for automated testing environments.
4.1 Cloudflare Official Turnstile Test Credentials
| Environment | Turnstile Sitekey | Turnstile Secret Key | Behavior |
|---|---|---|---|
| Staging / Preview / Local | 1x00000000000000000000AA |
1x0000000000000000000000000000000AA |
Always passes; emits dummy token XXXX.DUMMY.TOKEN.XXXX |
| Always Block Test | 2x00000000000000000000AB |
2x0000000000000000000000000000000AA |
Always fails validation |
| Interactive Test | 3x00000000000000000000FF |
1x0000000000000000000000000000000AA |
Always forces interactive visual puzzle |
| Production | Real Cloudflare Sitekey | Real Cloudflare Secret Key | Full Cloudflare ML bot risk scoring |
4.2 Playwright DOM Auto-Fill Helper
Headless synthetic scouts running on staging environments utilize setupTurnstilePageBypass(page):
- Injects a lightweight init script before document load.
- Intercepts
window.turnstile.render()to immediately invokeoptions.callback('XXXX.DUMMY.TOKEN.XXXX'). - Attaches a
MutationObserverthat automatically populates any<input name="cf-turnstile-response">elements dynamically created in the DOM. - Server-side verification helper
verifyTurnstileTokenvalidates dummy tokens offline for test secrets without calling external Cloudflare APIs.
5. Cloudflare Edge Architecture & Integration Options
5.1 Architecture Comparison
flowchart TD Scout["Headless QA Scout (Playwright)"] -->|"Outbound Request + Signed Headers"| Edge{"Cloudflare Edge"}
subgraph Staging_Zone ["Staging & Preview Deployment Zone"] Edge -->|"Host matches *-staging.* or *-preview.*"| GateCheck{"Verify Scout Headers"} GateCheck -->|"Valid HMAC + Fresh TS"| BypassPass["Skip SBFM / WAF Challenges (HTTP 200)"] GateCheck -->|"Invalid / Missing / Expired"| NormalSec["Enforce Standard Turnstile / WAF (HTTP 403)"] end
subgraph Production_Zone ["Production Deployment Zone"] Edge -->|"Host matches apex production"| ProdLockdown["Production Lockdown (HTTP 403)"] ProdLockdown -->|"Unconditional Deny"| ProdSec["Full Production Bot Management & WAF"] end5.2 Pattern A: Cloudflare Worker Ingress Middleware (Recommended)
- Mechanism: Cloudflare Worker isolate receives the incoming
Request, extractsX-Synthetic-Scout-*headers, recomputes the HMAC-SHA256 signature usingcrypto.subtle, validates the timestamp againstDate.now(), and checks host policy. - Latency Impact: $<1$ ms execution overhead in V8 isolate.
- Benefits: True cryptographic security, dynamic replay protection, multi-key rotation, structured error diagnostics, and 100% environment isolation.
5.3 Pattern B: Cloudflare WAF Custom Skip Rules
- Mechanism: Cloudflare WAF Custom Rule configured with the
Skipaction:- Expression:
(http.host in {"bakery-staging.jacobmiller22.com", "software-agency-staging.jacobmiller22.com"}and any(http.request.headers.names[*] == "x-synthetic-scout-signature"))
- Action: Skip
http_request_sbfm(Super Bot Fight Mode) andhttp_ratelimit(Rate Limiting).
- Expression:
- Limitation: Cloudflare’s WAF Ruleset Expression engine cannot natively verify HMAC-SHA256 signatures or calculate timestamp arithmetic.
- Synthesized Recommendation: Deploy Cloudflare WAF Skip Rules at the zone boundary to exempt traffic bearing the signed scout headers from Super Bot Fight Mode, coupled with Cloudflare Worker Ingress Middleware (
scoutEdgeMiddleware) to enforce cryptographic signature authenticity and timestamp replay freshness.
6. Implementation Reference
The complete exploratory toolkit is implemented under scripts/scout/edge/:
scripts/scout/edge/types.ts: Configuration interfaces, header contracts, and verification result schemas.scripts/scout/edge/signer.ts: HMAC-SHA256 signing, canonical string normalization, and PlaywrightconfigureScoutBrowserContextrouting interceptor.scripts/scout/edge/verifier.ts: Edge verification engine, constant-time comparisons, andscoutEdgeMiddlewarefor Cloudflare Workers.scripts/scout/edge/turnstile.ts: Cloudflare Turnstile dummy test key resolution, server-side token validator, and Playwright DOM injection helper.scripts/scout/edge/verify-edge-runtime.ts: Tier 2 Behavioral Runtime Proof executable harness booting a live edge isolate server with real Playwright Chromium execution.scripts/scout/edge/edge-interop.test.ts: 29 unit tests covering all cryptographic, failure-mode, and guardrail scenarios.scripts/scout/edge/verify-edge-runtime.test.ts: Automated test runner integration for live network runtime proof.
7. Two-Tier Verification Results
Tier 1: Machine Gate
- Unit tests: 29/29 tests passed across 8 test suites in
scripts/scout/edge/edge-interop.test.ts. - Architecture & documentation taxonomy lint:
pnpm run lint:arch0 errors.
Tier 2: Behavioral Runtime Proof (Live Network & Headless Chromium)
Executed via tsx scripts/scout/edge/verify-edge-runtime.ts against an active edge HTTP server:
| Step | Scenario | Action / Probe | Expected | Actual | Pass/Fail | Notes |
|---|---|---|---|---|---|---|
| 1 | Authenticated Staging Ingress | GET /api/resource (Host: bakery-staging.jacobmiller22.com, valid HMAC) |
200 | 200 | 🟢 PASS | Valid HMAC-SHA256 signature granted bypass cleanly |
| 2 | Unsigned Staging Request | GET /api/resource (Host: bakery-staging.jacobmiller22.com, no headers) |
403 | 403 | 🟢 PASS | Blocked: missing required synthetic scout headers |
| 3 | Tampered Signature | GET /api/resource (corrupted signature hash) |
403 | 403 | 🟢 PASS | Blocked: cryptographic HMAC mismatch |
| 4 | Tampered HTTP Method | POST /api/resource using GET signature |
403 | 403 | 🟢 PASS | Blocked: signature bound to GET method, cannot be replayed as POST |
| 5 | Tampered URL Path | GET /admin using /api/resource signature |
403 | 403 | 🟢 PASS | Blocked: signature bound to /api/resource path, cannot access /admin |
| 6 | Replay Protection: Expired Timestamp | GET /api/resource (timestamp 350s old) |
403 | 403 | 🟢 PASS | Blocked: timestamp exceeds 300s expiration TTL |
| 7 | Clock Skew Guardrail: Future Timestamp | GET /api/resource (timestamp +120s in future) |
403 | 403 | 🟢 PASS | Blocked: forward clock skew exceeds 60s tolerance |
| 8 | Production Domain Lockdown (Hard Negative) | GET /api/resource (Host: bakery.jacobmiller22.com, valid HMAC) |
403 | 403 | 🟢 PASS | Blocked: bypass strictly forbidden on production hostnames |
| 9 | Key Identifier Validation | GET /api/resource (unknown keyId: scout-revoked-or-unknown) |
403 | 403 | 🟢 PASS | Blocked: keyId not registered in edge secret store |
| 10 | Turnstile Staging Bypass | POST /api/submit-form with dummy token XXXX.DUMMY.TOKEN.XXXX |
200 | 200 | 🟢 PASS | Verified: Cloudflare Turnstile dummy token passed staging gate |
| 11 | Playwright Dynamic Request Signing | signedPage.goto(/storefront) via configureScoutBrowserContext |
200 | 200 | 🟢 PASS | Browser requests dynamically signed on-the-fly with 100% pass rate |
| 12 | Playwright Unsigned Browser Interception | unsignedPage.goto(/storefront) without scout context |
403 | 403 | 🟢 PASS | Blocked: headless browser without signed headers rejected (HTTP 403) |
8. Mandatory Cleanup & Teardown Roadmap
Per the architectural constraints established in Epic #762 and Issue #766:
- Exploratory Workspace: All code in
scripts/scout/is exploratory spike prototyping. - Mandatory Teardown Invariant: Prior to productionizing the synthetic scout runner (whether as an isolated daemon repo
siteswarm-scoutor dedicated platform package), the temporaryscripts/scout/directory will be cleanly deprecated and reaped. - Canonical Documentation Ingestion: The edge authentication specifications and Cloudflare configuration patterns in this write-up will be distilled into
docs/architecture/EDGE_SECURITY.mdanddocs/architecture/SCOUT_RUNNER.md.