Reference

Check coverage

All 143 checks, by module, with the severity each finding carries. There are no tiers. Every scan runs every check — what varies is how much of your application the scanner is allowed to reach.

143
distinct checks
31
engine modules
139
signatures behind them
Before the check list

What changes coverage

Two scans can return very different amounts of detail, and it is never because one bought a better plan. Four things decide how deep a scan reaches.

Domain verification

All active probing

A DNS TXT record at _secscan-challenge.<domain>, or a file at /.well-known/secscan-verification.txt

Without it only passive checks run. This is the control that stops the platform being used as an anonymous attack proxy, so it fails closed — a lookup error denies rather than allows.

Credentials

The surface behind the login

A session cookie or bearer token you paste, or a form login driven by a headless browser

On most applications nearly everything of value sits behind auth. A scan that never signs in never sees it.

A second account

Broken access control (OWASP A01)

A second set of credentials, supplied alongside the first

The question is not whether a page is reachable but whether the wrong person can reach it. Comparing one account against nothing proves nothing.

An out-of-band collector

SSRF detection (OWASP A10)

Operator-side configuration (OOB_BASE_URL) — set on secscan.us

A server tricked into fetching an attacker URL produces nothing in its own response. Proof has to arrive somewhere else.

Unverified domains get passive checks only. Active probing stays locked until you prove you control the target, and the report says so explicitly rather than quietly returning less. See how verification works.

29 checks · scanner.ts

Response headers and cookies Passive

Passive analysis of the first response. The largest single module — CSP alone accounts for seven distinct findings, and cookies are graded differently depending on whether they carry a session.

Check Severity
No HTTPS / plaintext HTTP Critical
Missing Content-Security-Policy High
CSP script-src contains a wildcard High
CSP is report-only, not enforced Medium
Weak CSP — unsafe-inline or unsafe-eval in script-src Medium
CSP allows inline styles Low
CSP missing object-src 'none' Low
CSP missing base-uri directive Low
Missing HSTS Medium
HSTS max-age too short under 6 months Low
Missing clickjacking protection (X-Frame-Options) Medium
Mixed content on an HTTPS page Medium
Permissive CORS — wildcard origin Medium
Missing X-Content-Type-Options: nosniff Low
Missing Referrer-Policy Low
Missing Permissions-Policy Low
Missing Cross-Origin-Opener-Policy (COOP) Info
Missing Cross-Origin-Embedder-Policy (COEP) Info
Missing Cross-Origin-Resource-Policy (CORP) Info
Missing Cache-Control headers Info
Server version disclosure Info
X-Powered-By discloses the stack Info
Session cookie missing Secure High
Session cookie missing HttpOnly Medium
Session cookie missing SameSite Medium
Non-session cookie missing Secure Low
Non-session cookie readable by JavaScript Info
Non-session cookie missing SameSite Info
Insecure deserialization — serialized object in a cookie lives in deserializationProbe.ts, not this file; Java/PHP/Ruby/pickle magic in a Set-Cookie value (CWE-502); JWTs excluded High
18 checks · probes.ts

Active HTTP probes

Individual requests to specific paths, methods and origins. Every path hit is confirmed against the target’s own catch-all response before it is trusted.

Check Severity
Supabase tables exposed — RLS disabled Critical
Flask debugger console exposed Critical
Verbose error page exposes stack trace or debug info CWE-209; Node.js/Python/PHP/Rails/Java/ASP.NET/Whoops/Laravel/Django signatures — the non-Flask branch of the same check Medium
Sensitive file or path publicly readable 78 paths — .env, .git, actuators, admin panels, WEB-INF, backups Varies
CORS — credentials allowed from an arbitrary origin High
CORS — origin reflected without an allowlist High
Dangerous HTTP methods advertised PUT, DELETE, PATCH High
HTTP traffic not redirected to HTTPS High
Directory listing enabled Medium
Open redirect Medium
HTTP TRACE enabled (cross-site tracing) Medium
HTTP CONNECT enabled Medium
External resources missing Subresource Integrity Medium
X-Frame-Options misconfigured Medium
robots.txt discloses sensitive paths Low
Rate limiting not advertised in response headers a header check only; it does not claim rate limiting is absent Low
Missing security.txt (RFC 9116) Info
Supabase detected — verify RLS Info
9 checks · dnsChecks.ts

DNS and email authentication Passive

Resolved over Cloudflare DNS-over-HTTPS. Needs no access to your registrar.

Check Severity
SPF uses +all — any sender authorised Critical
SPF record missing Medium if the domain has no MX High
DMARC record missing High
SPF uses ?all (neutral) Medium
DMARC policy is p=none Medium
SPF exceeds the 10 DNS lookup limit Low
DKIM records missing probes 42 selectors Low
DMARC missing rua= report address Info
DNSSEC not enabled Info
3 checks · mailTls.ts

Mail transport security Passive

SPF and DMARC say who may send mail as your domain. They say nothing about whether that mail is encrypted in transit, so a site can score perfectly on HTTPS while its password-reset mail is relayed in cleartext. This opens a real SMTP conversation with each MX on port 25 — the port every message from the outside world arrives on.

Check Severity
MX TLS certificate expired High
MX does not advertise STARTTLS Medium
MX TLS certificate expires within 21 days Low
9 checks · nextjsProbe.ts

Next.js __NEXT_DATA__ exposure Passive

Next.js serialises server props into a JSON blob in the page. Anything a getServerSideProps handler forgot to strip is sitting in the HTML, readable without running any JavaScript.

Check Severity
Supabase service_role key in __NEXT_DATA__ Critical
AWS access key ID Critical
AWS secret access key Critical
Stripe live secret key Critical
GitHub token Critical
Private key Critical
Hardcoded database connection string Critical
SendGrid API key High
Slack token High
9 checks · structuredData.ts

Structured data and social metadata Passive

Structured data is generated by a CMS or a build step and routinely carries more than its author realised into a public document. The first three findings are genuine exposure and carry weight; the rest are presentation quality and are Info at weight zero — a site with no og:image must never grade as less secure than one with it, or the grade stops meaning security.

Check Severity
Internal hostname exposed in JSON-LD Low
Social preview asset loaded over http:// from an HTTPS page Low
Canonical URL points to a domain you do not own a classic SEO-injection symptom Low
Malformed JSON-LD Info
JSON-LD missing @context or @type Info
No structured data found Info
Incomplete Open Graph metadata Info
Twitter Card metadata absent Info
Page excluded from search indexes Info
7 checks · apiProbe.ts

API surface testing

Endpoints are recovered from an exposed OpenAPI document where one exists, otherwise from string literals in the JS bundle — a single-page app exposes no forms or query strings to discover.

Check Severity
SQL injection in a query, path or JSON body parameter Critical
Record endpoint serves another account’s data (IDOR) Critical
Write verb answers an unauthenticated caller with 404 (BFLA) Critical
Endpoint returns data with no session at all High
Response carries hashes, tokens, keys or card data High
Endpoint never throttles a burst Medium
Request body declares privilege-bearing fields Medium
7 checks · cveCheck.ts

Known CVEs and end-of-life software

Detected versions are queried against OSV.dev; severity follows the CVE’s own CVSS score. End-of-life checks are separate — unsupported software has no CVE for the patches that will never be written.

Check Severity
Detected version matched against OSV.dev Varies
IIS 6.0 — CVE-2017-7269 WebDAV RCE Critical
PHP end-of-life (5.x, 7.0–7.3) Critical
Apache end-of-life (1.x, 2.2) Critical
Nginx end-of-life High
Nginx version with a known CVE Varies
Apache version with a known CVE Varies
1 check · manifestSca.ts

Dependencies named in an exposed manifest

When a target has already published its own package.json, the versions in it are read, not guessed, and checked against OSV.dev. It never fetches a manifest that was not already found exposed.

Check Severity
Vulnerable dependency named in an exposed manifest named from the file the target itself leaked Varies
9 checks · supabase-probes.ts

Supabase

The anon key is extracted from the bundle, table names come from the PostgREST schema endpoint merged with every .from("table") call already in the same bundle — Supabase now blocks anon-key schema listing on new projects, so the bundle scrape is what keeps this working — and up to 12 tables are tested with real unauthenticated calls. The anon key itself is never flagged — it is public by design.

Check Severity
service_role key in client-side JavaScript bypasses every RLS policy Critical
Tables return rows unauthenticated — CVE-2025-48757 Critical
Tables accept unauthenticated INSERT Critical
Tables reachable but currently empty no policy, just no data yet High
Storage bucket list exposed to the anon key Medium
Files in a storage bucket listable with the anon key a file name is returned, not just a bucket name Medium
Email confirmation disabled with sign-up open read from the Auth settings the server publishes Low
Supabase detected, RLS appears configured Info
Supabase backend detected Info
6 checks · jwtAnalysis.ts

JWT analysis Passive

Tokens are read from headers and HTML already fetched. No extra requests.

Check Severity
alg:none — signature verification bypass Critical
Empty signature segment Critical
Missing exp claim — token never expires High
HS256 without expiry High
Excessive lifetime (over 365 days) Medium
Sensitive data in the payload Medium
3 checks · accessControlProbe.ts

Broken access control

OWASP A01, the highest-ranked risk category and the one automated scanners usually skip. The same URL is requested as the primary account, as a second account, and as nobody, then the three responses are compared. The second account is one you supply, or, only if you tick the option for that scan, one the scan creates through your public signup form.

Check Severity
Second account served the first account’s record Critical
Records reachable by altering the identifier Critical
Record served in full with no session High
4 checks · firebase-probes.ts

Firebase

Twenty common collection names are tried against the Firestore REST API. The Firebase API key is not flagged — it identifies the project and is public by design.

Check Severity
Firestore returns documents unauthenticated Critical
Realtime Database returns data unauthenticated Critical
Cloud Storage bucket lists files unauthenticated flagged only when a file name is returned High
Firebase detected, rules appear restrictive Info
3 checks · storageProbe.ts

Object storage exposure

Bucket references are extracted from HTML and JS, then listed read-only.

Check Severity
Public S3 bucket listing High
Public Google Cloud Storage bucket listing High
Public Azure Blob container listing High
2 checks · baasProbes.ts

PocketBase and Appwrite

The same open-backend problem on two less common platforms, detected from page HTML and inline JS and then tested live.

Check Severity
PocketBase collections readable unauthenticated Critical
Appwrite collections readable unauthenticated Critical
4 checks · graphqlProbe.ts

GraphQL

Confirmed by a real introspection response rather than by the word "graphql" appearing on a page.

Check Severity
Schema introspection enabled in production Medium
Field suggestions enabled (“Did you mean…” leaks schema names) Low
Query batching enabled three operations sent as an array must come back as three results Low
IDE exposed (GraphiQL, Playground, Apollo Sandbox, Altair) the page must be the IDE itself, not an app shell Medium
4 checks · injectionProbe.ts

Injection probing

Candidate parameters are collected from the URL, in-page forms and links, capped at 20. Detection only — nothing is exploited and no data is extracted.

Check Severity
SQL injection (error-based) a SQL error signature absent from the baseline Critical
Reflected cross-site scripting a random canary must reflect back unencoded, in a response a browser renders as HTML High
Server-side template injection an arithmetic expression must come back computed, between random tokens we placed around it Critical
HTTP header injection (CRLF) a header with a random name that we injected must appear in the response Medium
1 check · worker.ts

TLS

Delegated to Qualys SSL Labs, started in parallel with the first request and waited on for up to 120 seconds. Certificate expiry from the same result feeds the monitoring alerts.

Check Severity
SSL Labs grade C or below F is Critical, C is Medium Critical
1 check · recon.ts

Recon — ports, DNS and subdomains

A TCP-connect sweep over 33 common ports with a banner grab, alongside DNS record enumeration and subdomain discovery from crt.sh certificate transparency logs plus a wordlist, capped at 100 resolved results.

Check Severity
Unexpected open port severity per port Varies
2 checks · crawler.ts

Site crawl

Up to 20 internal pages, with the header and cookie checks re-run on each and 8 high-value paths probed per page. A site is rarely uniform — the login page and the marketing home page often ship different headers.

Check Severity
Header or cookie failure on an inner page Varies
Sensitive path found on a crawled page 8 paths per page Varies
1 check · subdomainTakeover.ts

Subdomain takeover

CNAME chains are followed and matched against 19 provider fingerprints — S3, Heroku, GitHub Pages, Netlify, Vercel, Azure, Fastly, Shopify, Fly.io, Render, Railway and more.

Check Severity
Dangling CNAME to a claimable service Critical
1 check · ssrfProbe.ts

Out-of-band SSRF

A URL pointing back at a collector, carrying a token unique to one injection point, is planted in parameters whose names say they carry a URL. A callback proves the vulnerability — there is effectively no false positive, which is why it carries confidence 95.

Check Severity
Server fetches a URL supplied in a parameter Critical
1 check · pathTraversal.ts

Path traversal

URL parameters probed with encoded and double-encoded traversal payloads.

Check Severity
Path traversal / local file inclusion Critical
1 check · sourceMaps.ts

Source map exposure

Each JS bundle is checked for an adjacent .map file and for a sourceMappingURL comment pointing at a reachable one.

Check Severity
Source map publicly accessible High
1 check · healthEndpointProbe.ts

Health endpoint disclosure Passive

A public health check is normal. One that also tells strangers the server uptime, memory, instance name or runtime version is free fingerprinting. Reported as Info, never higher, and a bare {"status":"ok"} is never flagged.

Check Severity
Health endpoint discloses runtime details Info
1 check · apiDocsProbe.ts

API documentation exposure

Requires a parseable OpenAPI schema or a real Swagger UI bundle, not a keyword match. A found spec also feeds the API surface tests above.

Check Severity
OpenAPI / Swagger documentation exposed Medium
1 check · jsScanner.ts

JavaScript secret scanning

Inline scripts plus up to eight external files, 512 KB each, matched against 34 credential patterns with entropy thresholds. Public-by-design keys — pk_live_, sb_publishable_, Firebase AIza… — are never flagged on their own, and a JWT is only a credential leak when its payload carries an identity claim.

Check Severity
Credential found in JavaScript 34 patterns Varies
2 checks · aiFeatureProbe.ts

AI features in client code

Read from the same JavaScript the browser downloads, in the site's own files only, not a vendor widget. Nothing in this module sends a request to an AI provider or a chat endpoint. The one active AI check, below, only runs when a system prompt was found here, and it never asks a model to judge anything.

Check Severity
AI provider called directly from the browser a bring-your-own-key tool is legitimate; a key found in the code is a separate Critical Low
AI system prompt shipped in client-side code anyone can read it Low
1 check · promptInjectionProbe.ts

AI prompt injection (system prompt extraction)

Runs only on a verified-ownership scan, and only when the check above already found the site's system prompt in its own JavaScript. That known text is the ground truth: at most two requests ask the site's chat endpoint to repeat its instructions, and the finding needs a long word-for-word match of the prompt already found, never a judgement of what the reply looks like.

Check Severity
Prompt injection extracts the system prompt Medium
1 check · raceConditionProbe.ts

Race condition on a one-time action

Off unless a scan asks for it, and then only on a verified-ownership scan with a signed-in test account. It sends five simultaneous identical requests to at most three endpoints named like a redeem, coupon, promo or claim action, and reports it only when two or more succeed. A correctly guarded endpoint rejects the repeats. This can act on the test account, which is why it is never on by default.

Check Severity
One-time action succeeds more than once when requested at the same time High
1 check · githubSourceProbe.ts

Secrets in a public GitHub repository

Optional, and only when a scan names a public repository. Reads a fixed list of configuration, environment and migration files through GitHub's public API, with no token and no cloning, and matches them against the same 34 credential patterns as the JavaScript scan. A private, missing, rate-limited or unreachable repository is recorded as not scanned, never as clean.

Check Severity
Credential found in a public repository's source 34 patterns Varies
Not counted as checks

Signature tables

Four checks work by iterating a lookup table. Those 139 entries are signatures, not checks — /.env being exposed and /.git/config being exposed are one check, run twice. Counting them individually is how scanners advertise numbers that mean nothing.

TableEntriesSource
Sensitive paths probed 78 probes-data.ts
Secret patterns matched 34 secret-pattern-data.ts
Takeover fingerprints 19 subdomain-service-data.ts
Paths probed per crawled page 8 crawler-data.ts
Scoring

How the grade is calculated

Risk accumulates per finding, then maps to a letter. The weighting is deliberately steep — one Critical outweighs six Highs, because a single unauthenticated data read is not offset by good headers.

FindingPoints
Critical +30
High +15
Medium +5
Low +1
ScoreGrade
0–10 A
11–25 B
26–45 C
46–65 D
66+ F

The grade also drives rescan frequency if you turn on continuous monitoring — an A is rechecked every 14 days, an F every 3.

After the scan

Compliance mapping

The scan does not assess compliance — no scan can. What it does is map each finding to the specific controls it is evidence for, so a finding can be handed to the person who owns that control. Nothing is scored against a framework, and a clean scan is never reported as a passed control.

FrameworkVersionWhat a mapped finding means
SOC 2 2017 TSC (rev. 2022) Trust Services Criteria. Most criteria cover policy, personnel and process no scan can observe; findings speak only to the technical subset.
PCI DSS 4.0.1 Applies only where cardholder data is stored, processed or transmitted. Requirement 11.3.2 expects an ASV scan — this is not one.
ISO/IEC 27001 2022 Annex A Annex A controls. Certification is granted by an accredited body against the management system as a whole, not against a scan result.
OWASP ASVS 4.0.3 The Application Security Verification Standard is built for exactly this kind of testing, so the mapping is tightest and most meaningful here.
NIST SP 800-53 Rev. 5 Most controls cover policy, personnel and operations no scan can observe; findings speak only to the technical subset.
HIPAA Security Rule 45 CFR 164.312 (technical safeguards) Applies only to covered entities and business associates handling electronic protected health information. Whether an addressable specification is required is decided by the covered entity’s own risk analysis, which no scan can perform.

This mapping is not a compliance assessment, an audit, or an attestation. An application scan observes the HTTP surface of a running system at one point in time; SOC 2, PCI DSS and ISO 27001 are largely about policy, process and personnel that no scan can see. Only a licensed CPA firm issues a SOC 2 report, only a QSA validates PCI DSS, and only an accredited body certifies ISO 27001.

Every account gets 3 free scans every month — every one of these checks, no tier to pick.

Run these 143 checks on your site →