Skip to content

Configurable CORS proxy, Cloudflare Worker option, and Recon/Vuln Scan reliability fixes - #8

Open
BruceLittle wants to merge 4 commits into
mainfrom
claude/stoic-archimedes-qnrnxl
Open

BruceLittle wants to merge 4 commits into
mainfrom
claude/stoic-archimedes-qnrnxl

Conversation

@BruceLittle

Copy link
Copy Markdown
Owner

Summary

  • Makes the CORS proxy endpoint configurable (a "Proxy endpoint" field next to the on/off toggle), defaulting to the public corsproxy.io but able to point at any endpoint, including a private one
  • Adds tools/zeithawk/cors-proxy-worker/ — a ready-to-deploy Cloudflare Worker that acts as a private CORS proxy under your own account. A Google Apps Script web app can't fill this role: it has no way to set Access-Control-Allow-Origin on its own response at all (documented in tools/apps-script-backend/Code.gs, which is why that backend uses JSONP instead)
  • Fixes a real regression: the CORS-proxy toggle previously force-routed every request (including Recon's DNS/RDAP lookups) through the proxy unconditionally, even for targets like dns.google that already work fine unproxied. fetchDirectOrProxied() now tries a direct fetch first and only falls back to the proxy if that fails — applied consistently across Repeater/Intruder, Recon, and Vuln Scan
  • Fixes a real bug: in Recon's DNS lookup, an unexpected (non-array) Answer shape for any one of the 7 parallel record-type queries threw inside a shared forEach, silently dropping every record type queried after it in the array (NS, CNAME, SOA after an early failure). Each record type is now handled in its own try/catch with an explicit Array.isArray check
  • Documents that a Claude Artifact preview can't make real outbound network requests at all (its own CSP blocks arbitrary cross-origin fetch()), confirmed today while debugging live — this tool needs to run as an actual hosted page (e.g. GitHub Pages) to do anything real
  • Updates tools/zeithawk/README.md throughout to match

Test plan

  • Verified via Playwright: default proxy state (on), toggling off reverts to direct requests, a custom proxy endpoint gets used correctly and persists via localStorage
  • Verified the direct-then-fallback behavior via a real local HTTP server (not file://, which doesn't enforce CORS the way a hosted page does) — a CORS-friendly target (dns.google) is hit directly with zero dependency on the proxy
  • Verified the DNS cascade-loss fix directly: mocked a malformed (non-array) Answer for NS specifically, confirmed SOA (which comes after NS in the query-type list) still renders correctly instead of silently disappearing
  • Full regression pass across all seven tabs — no console/page errors
  • Live-debugged today against zeitview.com on a real GitHub Pages deployment with a real (keyed) corsproxy.io account — confirmed the root cause of the original "Failed to fetch" reports was the Claude Artifact sandbox, not this code; found and fixed the DNS cascade bug against real API responses
  • Re-verify Recon and Vuln Scan against zeitview.com on GitHub Pages once this is merged, since testing so far has been against the pre-fix code still on main

🤖 Generated with Claude Code

https://claude.ai/code/session_01SkupxCaLk9Nnq24YhigdAn


Generated by Claude Code

Adds a "Proxy endpoint" field next to the CORS proxy toggle so it can be
pointed at a private proxy instead of the default public corsproxy.io.
Includes a ready-to-deploy Cloudflare Worker (tools/zeithawk/cors-proxy-worker/)
that does the job under your own account, plus copy-paste deployment
steps.

The existing Apps Script backend can't fill this role: Apps Script web
apps have no way to set Access-Control-Allow-Origin on their own
response at all (that's why Code.gs uses JSONP for its one read path
instead of a proxy) — a Cloudflare Worker can set CORS headers freely,
so it's the viable private-proxy option.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SkupxCaLk9Nnq24YhigdAn
Confirmed today: Vuln Scan (and everything else in ZeitHawk that makes
outbound requests) fails with a generic "Failed to fetch" when run from
a claude.ai artifact preview, regardless of target, CORS proxy, or proxy
credentials — because the artifact sandbox's own CSP blocks fetch() to
arbitrary third-party domains. The exact same requests work correctly
once hosted as a real page (e.g. GitHub Pages). Adds a "Running it"
section pointing at GitHub Pages as the way to actually use this tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SkupxCaLk9Nnq24YhigdAn
Recon's DNS lookups (dns.google) and RDAP lookups (rdap.org) already
worked without a proxy in many cases, since dns.google sends its own
permissive CORS headers. Force-routing every request through the
configured proxy (added when the CORS-proxy toggle was introduced) meant
a single misbehaving or misconfigured proxy endpoint could break lookups
that used to work fine unproxied — this is what broke Recon.

fetchDirectOrProxied() now tries a direct fetch first and only falls
back to the proxy if that fails outright, applied consistently across
Repeater/Intruder, Recon's DNS/RDAP lookups, and Vuln Scan. Targets that
already allow cross-origin access keep working with zero dependency on
a third party; targets that need the proxy still get it on the retry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SkupxCaLk9Nnq24YhigdAn
Recon runs 7 DNS-record-type queries in parallel and processes the
results in a single forEach. An unexpected (non-array) Answer shape for
any one record type threw inside that loop, which silently killed
processing for every type after it in the array — NS, CNAME, and SOA
disappeared even though A/AAAA/MX/TXT (processed first) rendered fine.
This is what caused zeitview.com's real NS records to show as "not
found" despite the underlying DNS data being correct.

Each record type's result is now handled in its own try/catch with an
explicit Array.isArray check, so one malformed response is skipped
without affecting the rest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SkupxCaLk9Nnq24YhigdAn

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants