Browser-side defenses
Eight scanners test the rules a browser enforces on the user's behalf: which origins may read a response, which cross-site requests the server accepts, where a redirect may land, which protective headers are set, and what the page itself ships to the client. All of them work from one rendered snapshot of the target plus a handful of header-level requests.
How this group works
The ingestion phase renders the target once and keeps what it saw. Four of these scanners read only that snapshot and never touch the network. The other four send a few requests that differ from a normal one by a single header or query parameter, then read a single header or status in the reply. Every scanner has one rule and one guard.
1Ingestion renders the target once with Playwright and keeps everything it saw: the HTML, the first-party scripts, the cookies and response headers, and any sourceMappingURL comment. The eight scanners in this group all start from that.
2Four scanners never send a request. Mixed-content, SRI, client-exposure and the passive half of CSRF pattern-match the snapshot: an http:// script on an HTTPS page, a CDN script without integrity=, a Supabase JWT whose role claim is service_role, a cookie without SameSite.
3The other four send a few header-level requests and read one thing in the reply: CORS reads Access-Control-Allow-Origin, CSRF reads the status code behind a forged Origin, open-redirect reads Location, security-headers reads the header map, source-map fetches the guessed .map.
4Each rule carries a guard against a cheap false positive: SRI ignores first-party URLs, source-map demands "sources" or "mappings" in the body because SPA catch-alls answer 200 to anything, security-headers collapses a server-wide miss into one finding, and clickjacking accepts CSP frame-ancestors in place of X-Frame-Options.
5Findings range from LOW (an http:// image) to CRITICAL (a service_role key, or wildcard CORS with credentials). All eight run in the default quick depth and in url-only mode. Credentials are optional: they only let the probes land behind the login wall.
Scanners in this group
CSRF
A state-changing request with a forged Origin that still gets a 2xx, cookies without SameSite, and POST forms without a token field.
CORS
Three Origin probes per path prefix and four rules in strict order, from wildcard-with-credentials (Critical) down to a bare wildcard (Medium).
Open redirect
Seventeen parameter names and seven paths, four payloads in order, and a Location header that must point off-site before anything is reported.
Security headers
Six protective headers, two disclosure headers, the frame-ancestors alternative, a version regex for Server, and server-wide deduplication.
Mixed content
An HTTPS page that loads http:// scripts, styles or frames (Medium) or images (Low). Passive, from the snapshot; nothing is fetched.
Subresource integrity
Cross-origin scripts (Medium) and stylesheets (Low) loaded without an integrity hash. First-party resources are excluded.
Source maps
Guessed and discovered .map URLs are fetched and confirmed by their JSON markers, so an SPA's 200-for-everything never counts. First-party is High.
Client exposure
First-party JS only: a Supabase service_role JWT (Critical), internal or staging URLs, and un-replaced process.env placeholders (Low).
At a glance
All eight are DAST scanners that run in the default quick depth and need only a target URL. None needs an API key, a binary or --depth deep. Credentials are optional everywhere: the four that send requests attach the auth headers when they exist.
| Scanner | What it looks at | What it reports | Severity | Needs |
|---|---|---|---|---|
| CSRF | Every POST/PUT/PATCH/DELETE endpoint, plus the snapshot's cookies and POST forms | Forged Origin accepted (2xx); cookie without SameSite or with SameSite=None; POST form with no known token field | Medium–High | URL; credentials optional |
| CORS | One GET per distinct two-segment path prefix, with three Origin values | Wildcard with credentials; reflected Origin; null Origin; bare wildcard | Medium–Critical | URL; credentials optional |
| Open redirect | Parameters named like a redirect target and paths such as /login or /auth/callback | 3xx with an off-site Location; JavaScript or meta-refresh redirect in the body | Medium–High | URL; credentials optional |
| Security headers | A GET to every unique URL, shortest first | HSTS, CSP, X-Content-Type-Options, Permissions-Policy, Referrer-Policy missing; no clickjacking protection; Server version; X-Powered-By | Low–High | URL; credentials optional |
| Mixed content | Captured HTML and first-party JS of an HTTPS page | http:// script, link or iframe (Medium); http:// img (Low); at most 10 per kind | Low–Medium | HTTPS URL; no requests |
| SRI | Captured HTML: <script src> and <link rel=stylesheet> on other origins | External script without integrity (Medium); external stylesheet without integrity (Low); at most 20 | Low–Medium | URL; no requests |
| Source map | sourceMappingURL hits from ingestion plus <asset>.map for every first-party JS asset, up to 40 | A reachable .map whose body contains "sources": or "mappings": first-party High, third-party Low | Low–High | URL; credentials optional |
| Client exposure | First-party JS only (vendor bundles filtered out) | JWT with role service_role (Critical); internal, localhost or staging URL (Low); un-replaced process.env / import.meta.env name outside the public prefixes (Low) | Low–Critical | URL; no requests |
Why this class matters
These controls are the browser's half of the security model. The server can be perfectly authenticated and still lose: a reflected CORS origin lets evil.com read a logged-in user's API responses; a missing SameSite attribute lets evil.com submit a transfer with the victim's cookie; an open redirect turns your domain into a phishing link; a missing CSP means an injected script runs unhindered; a service_role key in the bundle bypasses Row Level Security for anyone who views source. Each of these is one header or one line of configuration, which is why they are cheap to test and cheap to fix.
Netflix (2006): CSRF could change account email, password and DVD queue because the site lacked CSRF tokens. ING Direct (2008): CSRF initiated fund transfers from a victim's account when they visited a malicious page while logged in. Cryptocurrency exchanges (2016–2018): several reflected arbitrary Origin headers in CORS responses, letting attacker-controlled sites read authenticated responses with balances and API keys. British Airways (2018): the Magecart XSS attack was worsened by the absence of a Content Security Policy; script-src 'self' would have blocked the injected third-party script. Google (ongoing): its redirect endpoints have been repeatedly abused in phishing campaigns so links appear to originate from google.com.