Web Security Audit (Non-Invasive)
A site-owner-friendly security review grounded in observable, read-only evidence — security headers, TLS configuration, exposed paths, third-party scripts, cookies — never active exploitation. Output is multi-audience: a plain-English summary for the site owner, prioritized fixes with who-fixes tags, and developer-ready snippets in collapsed blocks.
Scope & ethics
This skill is defensive only:
- ✅ HTTP HEAD/GET to publicly-listed pages
- ✅ Checks of well-known paths (
/.env,/.git/config,/robots.txt,/sitemap.xml,/admin,/api/health) — these are the same checks any attacker runs in the first 30 seconds; if they're exposed, you want to know - ✅ Reading TLS certificate and headers
- ✅ Static analysis of returned HTML/JS for third-party origins, inline scripts, SRI
- ❌ No brute-forcing, password spraying, or credential testing
- ❌ No SQL/XSS/SSRF payload injection
- ❌ No rate-limit probing or denial-of-service testing
- ❌ No scanning of pages requiring authentication (without explicit credentials and authorization)
If the user wants active pentesting, refuse and recommend a dedicated pentest engagement with signed authorization.
When to use
- The user has a deployed site URL and asks "is this secure?"
- The user wants a header-and-config check before going live or after a relaunch.
- The user mentions GDPR / EU Accessibility Act / SOC2 prep and wants a quick web-surface review.
- The user is choosing between vendors and wants a defensive baseline check on the candidates.
When NOT to use
- Pre-production code review → use
security-review(git diff based) - Active pentesting → refuse and recommend a licensed firm
- Network / infrastructure audit (cloud config, IAM, S3 buckets) → out of scope; recommend a cloud-security skill
- Application-logic bug hunting (business-logic flaws) → requires authenticated access and structured test plan
Step 1 — Ask before auditing (max 4 quick questions)
Phrase questions for a non-technical site owner, not a security engineer. Skip any you can already infer from the URL or prior conversation.
-
What does the site do? (pick the closest)
- Marketing / brochure site (no login)
- Content / blog (no login)
- Sign-ups or accounts (login + user data)
- Payments / e-commerce
- SaaS app (login + customer data)
- Other — describe
Each shifts the audit weight: a brochure site cares most about headers and trackers; a SaaS app cares most about auth, cookies, and API exposure.
-
Do you collect any personal data from visitors? (emails, names, payment info, anything)
- Yes
- No
- Not sure
If yes → unlock the GDPR / privacy / cookie-consent dimensions.
-
Where are most of your visitors? — Singapore, EU, US, global? Drives which compliance regimes are mentioned (GDPR vs CCPA vs Singapore PDPA vs none).
-
(Optional) Do you have authorization to audit this site? — Only ask if the URL doesn't obviously belong to the user (e.g., they're auditing a vendor). If they say no, refuse and explain why.
If the user wants to skip everything, default to: site type = inferred from homepage, collects data = "assume yes" (safer), geography = inferred, authorization = "assumed, ask if unclear."
Step 2 — Gather evidence
See references/evidence-gathering.md for all required checks: response headers, TLS, information-
disclosure path probes, HTML/script inspection, cookie inspection, form surface, third-party
inventory, and privacy/consent checks.
Step 3 — Tag every finding
- [Observed] — Directly visible in response headers, returned HTML/JS, or a 2xx on a probed path.
- [Inferred] — Best-guess from indirect signals (e.g., "likely vulnerable to clickjacking because no X-Frame-Options and no CSP frame-ancestors"). Always state both halves of the inference.
- [Needs user data] — Requires server logs, secrets manager config, or DB access the user didn't share.
Never present [Inferred] as fact. Security findings carry weight; a false positive damages trust faster than a missed real issue.
Step 4 — Run the framework
Audit these 13 dimensions. Sequence and weight by site type (Step 1 Q1).
- HTTPS & Transport — HTTPS reachable, HTTP→HTTPS redirect, HSTS present + sufficient
max-age, no mixed content, TLS 1.2+ (preferably 1.3), valid cert with >30 days to expiry. - Security Headers — CSP (presence > nothing; even
report-onlyis a start), X-Frame-Options or CSP frame-ancestors, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, Cross-Origin-* trio. - Cookies — Secure + HttpOnly + SameSite on session/auth cookies; flag overly long expiry.
- Information Disclosure — server fingerprinting headers, exposed source maps,
.env/.git/backup-file probes, verbose error pages, internal HTML comments, admin paths discoverable. - Authentication Surface (if applicable) — login page over HTTPS, no autocomplete=off on password (counter-intuitively, modern guidance says LET password managers fill), no password-policy hints leaking in errors ("user not found" vs "invalid credentials"), MFA available?
- Third-Party Scripts & Supply Chain — every third-party origin inventoried, SRI on as many as
possible, no unused tracker bloat (each = breach surface),
async/deferused to limit blast radius. - Input & XSS Surface — passive only: count forms, note framework (React/Vue/Svelte naturally
escape; raw template engines don't), check for
dangerouslySetInnerHTML-style patterns visible in returned HTML. - CORS & Cross-Origin — overly permissive
Access-Control-Allow-Origin: *on responses that include cookies (= credentialled CORS misconfig); legitimate*on public, no-cookie API responses is fine. - Subdomain & Asset Hygiene — preview deployments indexed/reachable? Forgotten staging URLs?
Vercel/Netlify build-IDs in headers?
vercel.jsonexposed? - DNS & Email Hygiene — SPF, DMARC (
p=rejectorquarantine), DKIM presence for any selectors found. Missing DMARC = anyone can spoof your domain in phishing emails. - Privacy & Compliance — privacy policy linked, cookie consent banner present and honoured (no pre-consent trackers), terms of service link, region-specific gates: GDPR (EU), Singapore PDPA, CCPA (California), UK DPA.
.well-known& Disclosure Channels —/.well-known/security.txt(RFC 9116) present with a contact email and policy link? Without it, security researchers have nowhere to report bugs.- Defaults & Framework Posture — vendor defaults left exposed (Next.js debug routes, Vercel
preview URLs not redirected to production, default WP login at
/wp-admin, etc.).
Step 5 — Severity rubric
| Level | Definition | Example |
|---|---|---|
| Critical | Direct exploitable exposure: secrets leaked, admin auth bypass, full source/database access from the public internet | .env returns 200 with API keys; /.git/config exposed; admin login with no MFA AND no rate limit; Access-Control-Allow-Origin: * with credentials |
| High | Defense-in-depth missing on attack surface that matters: no HSTS on banking/SaaS site, no CSP on site loading 5+ third-party scripts, session cookie missing HttpOnly + Secure | No HSTS + handling logins; CSP absent + many third-party scripts; mixed content on auth flow |
| Medium | Hardening gap, exploitable only in chained scenarios or against unusual user setups | Missing Permissions-Policy; server header leaks framework version; no SRI on third-party CDN; no security.txt |
| Low | Polish / best-practice | Referrer-Policy set to default rather than strict-origin-when-cross-origin; verbose x-powered-by; missing cross-origin-resource-policy |
Calibration: A brochure site missing CSP is Medium. A SaaS app handling user data missing CSP is High. Always weight by Step 1 Q1.
Step 6 — Produce the report
Write to web-security-audit-{{domain}}-{{date}}.md. See references/report-template.md for the
full report structure (sections 1–11) and the verbatim finding format with example.
See references/output-and-rules.md for output delivery instructions and hard rules.