GRC Oversight

How the public scanner works

The free GRC Oversight scanner performs only passive, browser-equivalent checks. This page is the policy URL our scanner's User-Agent advertises. It lays out exactly what it checks, what it doesn't, how the score is built, and where the abuse/consent line is drawn.

Overview

Passive, browser-equivalent checks only

A scan loads your site one time, the way a normal browser does on a first visit, plus a handful of bounded single-request lookups. It does not crawl, brute-force, fuzz, or attempt to authenticate. Every category below is described from the actual check implementation, not aspirationally.

Category 1

DNS & email hygiene

Public DNS record lookups against the registrable domain. These query public DNS resolvers, not your site.

SPF
Looks for a `v=spf1` TXT record at the apex domain. Missing SPF is flagged medium severity.
DMARC
Looks for a `v=DMARC1` TXT record at `_dmarc.<domain>`. Missing DMARC is medium severity; a present but monitor-only policy (`p=none`) is flagged low severity.
DKIM
Opt-in. DKIM keys live under per-selector records (e.g. `selector._domainkey.<domain>`) that can't be enumerated without knowing the selector, so by default the scanner reports a hint only ("checked: false") explaining that DKIM must be verified with your mail provider's selector, with no score impact. If you supply a selector on the scan form, it performs one additional passive TXT lookup at that name and checks for a record starting with `v=DKIM1` with a non-empty public key (`p=`); a missing or malformed record then does affect the DNS score. See our email authentication guide for more.
CAA
Looks up CAA records at the apex. No CAA record is flagged low severity (any CA can issue certificates for the domain).
DNSSEC
Checked via a DNS-over-HTTPS query for a DNSKEY record at the apex (Cloudflare's public resolver), because Node's built-in resolver can't query DNSKEY reliably. This is best-effort: some resolvers hide DNSKEY, so a negative result is reported as informational, not a hard failure.
Category 2

TLS / certificate

A single TLS handshake to the host on port 443 (the same handshake any browser performs on first visit) reads the certificate and negotiated protocol, then the socket is closed.

What's read
Negotiated protocol and cipher, certificate subject/issuer, validity window, subject alternative names, and whether the chain validates.
Grading
SSL-Labs-style hard caps: an expired, not-yet-valid, self-signed, or untrusted-chain certificate caps the grade at F or D regardless of protocol strength. TLS 1.0/1.1 caps at C; TLS 1.2 caps at A-; TLS 1.3 has no cap.
Not checked
Cipher suite ordering/preference, OCSP stapling, certificate transparency logs, or renegotiation behavior are not evaluated.
Category 3

HTTP security headers

Pure analysis of the response headers already captured during the single page load, with no extra network traffic. Scored with a Mozilla-Observatory-style modifier model (named credits/penalties per header, summed and mapped to a letter grade).

Strict-Transport-Security (HSTS)
Present with max-age ≥ 180 days is required to be considered good; missing HSTS is the largest single penalty.
Content-Security-Policy (CSP)
Missing CSP is a large penalty. Present but using `unsafe-inline` or lacking a `default-src`/`script-src` is flagged as weak (partial penalty).
X-Content-Type-Options
Must be exactly `nosniff` to count as good.
X-Frame-Options / clickjacking
Either `X-Frame-Options` or a CSP `frame-ancestors` directive satisfies this check.
Referrer-Policy
Any explicit value earns credit; absence is a small penalty.
Permissions-Policy
Presence earns a small credit; absence is informational only (no penalty) since it's a newer header.
HTTPS at the final hop
If the final loaded URL isn't HTTPS, this is the single largest penalty and is flagged critical.
Category 4

Cookies & consent

Inspection of cookies set during the single page load, plus detection of a visible consent/cookie banner. Both operate on data already collected, with no extra requests.

Cookie flags
Each cookie set on load is checked for Secure, HttpOnly, and a restrictive SameSite value. Missing Secure is medium severity; missing HttpOnly or SameSite is low severity.
Consent banner detection
Checks a list of common selectors and known CMP containers (OneTrust, Cookiebot, Usercentrics, and similar) for visibility on the loaded page.
Pre-consent tracking heuristic
If cookies were set on load and no consent banner was detected, this is flagged medium severity as a possible GDPR/ePrivacy issue. If no cookies were set and no banner exists, that's reported as informational only, not a violation.
Mixed content
On an HTTPS page, any observed http:// subresource requests are flagged medium severity (up to 25 URLs listed).
Category 5

Exposure checks

A single GET each to a small set of well-known sensitive paths. This is not a crawler and not a directory brute-forcer. It is the exact request a careful visitor's browser might make.

/.git/config, /.git/HEAD
Flags an exposed .git directory only if the response body content matches Git's actual file format (e.g. a `[core]` section or `ref: refs/`), not merely a 200 status. This avoids false positives from catch-all SPA routes.
/.env
Flags an exposed .env file only if the body looks like `KEY=VALUE` lines and is not an HTML page.
/.well-known/security.txt, /security.txt
A positive signal, not a vulnerability: presence of a valid security.txt (RFC 9116) with a Contact field is noted; absence is flagged informational, suggesting you publish one.

Each request is bounded (6-second timeout, ~4KB read cap), follows redirects manually rather than automatically (a redirect to a login or home page is treated as not-exposed, not a match), and sends the published scanner User-Agent below.

Category 6

Accessibility

An axe-core audit of the DOM already loaded for the header/cookie checks. It sends no additional network traffic.

Scoring
Each violation is weighted by both its axe impact level (critical/serious/moderate/minor) and the number of affected DOM nodes, with diminishing returns on node count so one noisy rule can't dominate the score.
What's surfaced
The top 8 violations, ranked by impact then node count, are shown as findings with a link to the axe-core remediation guidance for each rule.
If the page fails to load
Accessibility is reported as not-run with a note, rather than silently scored as perfect or zero without explanation.
What it does

Full check summary

The same six categories above, side by side with an explicit list of what the scanner never does.

Checks we perform

  • TLS / certificate inspection: one direct TLS handshake to read the certificate and negotiated protocol (graded SSL-Labs style).
  • HTTP security headers: analysis of the response headers from the single page load, scored with a Mozilla Observatory-style model.
  • DNS hygiene: public DNS record lookups (SPF, DMARC, CAA, DNSSEC, and an opt-in DKIM selector check). These query public DNS, not your site.
  • Cookies & consent: inspection of cookies set during the single page load and detection of a visible consent banner.
  • Exposure checks: a single GET each to /.git/config, /.git/HEAD, /.env, and /.well-known/security.txt, confirmed by content sniffing, not just a 200.
  • Accessibility: axe-core runs against the already-loaded page DOM and sends no additional network traffic.

What it never does

  • No crawling, spidering, or directory/path brute-forcing beyond the fixed, published list of exposure paths.
  • No port scanning, vulnerability exploitation, fuzzing, or injection attempts.
  • No login attempts and no submitting of forms. The scanner never interacts with page content beyond a single navigation.
  • No active vulnerability scanning (no CVE probing, no payload testing) and no authenticated checks of any kind.
  • No DKIM record verification. DKIM selectors can't be enumerated passively, so the scan reports a hint pointing you to your mail provider instead of a pass/fail.
  • No traffic to internal, private, or loopback hosts. Targets that resolve to private/CGNAT/link-local addresses are refused before any connection is attempted (SSRF guard).
  • No load beyond what a normal browser generates visiting a single page, plus a handful of bounded single-GET requests.
Scoring

Methodology and its limitations

The overall grade blends three category scores: security (headers, TLS, DNS, and exposure penalties) weighted 55%, privacy (cookies and consent) weighted 20%, and accessibility weighted 25%.

  • This is a heuristic, automated, passive scan. It is not a certification, not a penetration test, and not a substitute for a professional security assessment or accessibility audit.
  • A high grade means the checks above found no issues; it does not mean the site has no vulnerabilities. Authenticated flows, business logic, APIs, and anything not reachable from a single anonymous page load are entirely out of scope.
  • Category weights and per-header/per-violation point values are our own implementation choices, anchored to published rubrics (Mozilla Observatory for headers, SSL Labs grading conventions for TLS) but not identical to either. Grades from this scanner will not always match Observatory or SSL Labs exactly.
  • DNSSEC detection is best-effort (via a third-party DNS-over-HTTPS resolver) and can under-report a domain that has DNSSEC enabled.
  • Some checks degrade gracefully rather than failing the whole scan: if the browser-based page load fails, header/cookie/consent/accessibility results are reported as unavailable (not zeroed silently), while TLS/DNS/exposure checks that don't depend on the browser still run and report normally.
Identifying us

Published User-Agent

Every request the scanner makes carries an identifiable User-Agent that links back to this policy page:

GRCOversightScanner/1.0 (+https://grcoversight.com/scanner-policy; passive browser-equivalent checks only)

The single-GET exposure checks also send this User-Agent and honor your server's responses (a redirect to a login or home page is treated as not-exposed).

Abuse & consent boundaries

Rate limits and scan volume

The scanner is rate-limited to keep load minimal and prevent abuse. Limits are enforced in-process per source IP and per target host, sufficient for the current single-process deployment; if the app is ever horizontally scaled, this moves to a shared backing store behind the same interface.

Per source IP

Up to 5 scans per minute from a single client IP. Requests over the limit are rejected with a retry-after.

Per target host

At most 2 scans per minute against the same host, so no single domain is hammered.

Combined with the SSRF guard against internal/private targets and the bounded, single-request nature of every check, this keeps the scanner within what a normal browser visit already generates. Anyone scanning a domain they don't own should expect nothing more than that.

Opting out

Request exclusion

If you do not want your site scanned, contact us and we will exclude it. Because the scanner only runs on demand and stays within browser-equivalent traffic, it should never impact a healthy site, but we will honor exclusion requests.

See what the scanner finds

Get a guided demo, or start by scanning any domain for free.