Transparency
How Scorifya works
Scorifya is a configuration and hygiene checker, not a penetration test. This page explains what we observe, how scoring fits together, and what stays out of scope.
For how Scorifya fits next to deep TLS graders, browser-focused posture tools, and header-only checkers (category labels only—no product names), see How Scorifya compares to other tool types. For deploy-ready fixes aligned with common stacks, see stack guides.
What we observe
For the URL you enter, we perform a small set of public checks typical of a first-hop browser request (with redirects followed where applicable):
- HTTPS and redirects — TLS validity, certificate horizon, and whether HTTP is upgraded sensibly when port 80 responds.
- Security headers — presence and shape of headers such as HSTS, CSP, Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, X-Frame-Options / frame-ancestors, MIME sniffing, referrer policy, and related signals.
- Hygiene — obvious verbose banners or defaults that increase attack surface or erode trust, plus basic cookie attribute signals when Set-Cookie is visible on the response we see.
- DNS & email (passive) — TXT lookups for SPF and DMARC (including
_dmarcon the hostname and, when applicable, the parent label), a few common DKIM selector names, MX records for the hostname, CAA at the hostname and parent label when a parent exists, and when MX exists: MTA-STS (_mta-sts) and TLS-RPT (_smtp._tls) TXT hints. We also check BIMI atdefault._bimion the apex label (parent domain when the scan host is a subdomain, otherwise the host itself). We record whether a small curated set of subdomains resolve to public addresses. We do not port-scan or enumerate large subdomain wordlists. - TLS follow-up — besides the negotiated protocol/cipher on the main probe, we run a bounded set of short TLS handshakes: TLS 1.0 / 1.1 acceptance checks, optional TLS 1.2-only and TLS 1.3-only snapshots, and a small curated set of client cipher-list probes to see whether a legacy-heavy client can still negotiate weak suites. This is not exhaustive—we do not enumerate every cipher suite or client profile a server might accept. We also flag weak negotiated ciphers on the primary probe (including CBC on TLS 1.2) and undersized non-EC public keys on the leaf certificate.
We also fetch security.txt (RFC 9116) at /.well-known/security.txt, then /security.txt if needed, and flag a missing file or a file without a Contact: line. When Contact is present we record optional fields such as Expires, Canonical, Encryption, and Preferred-Languages in technical output and may surface informational notes (for example missing Expires or a Canonical mismatch). We fetch robots.txt on the same HTTPS origin for crawler-policy hygiene signals (not a substitute for access control). On the same HTML response we evaluate Cross-Origin-Opener-Policy (missing values are an informational finding) and Cross-Origin-Resource-Policy (we record the value; absence on top-level documents is common, while cross-origin triggers a short explanatory note). For HSTS, if your policy already looks "strong" by our baseline, we may add an informational preload hint: Chromium's preload program expects at least a one-year max-age, includeSubDomains, and the preload directive—submission is always optional.
What we do not do
- No exploitation, fuzzing, or vulnerability enumeration.
- No authenticated crawling or scanning behind logins.
- No malware or reputation feeds in the public score (scope may evolve; we will say so clearly).
- No arbitrary port scanning beyond HTTP/HTTPS behavior and the passive DNS checks above—so we do not, for example, probe SSH, databases, or RDP ports.
- No guarantee of compliance with any standard (PCI, SOC 2, etc.).
If you need assurance for contracts or incidents, engage a qualified security assessor. See the FAQ for plain-language boundaries.
How scoring fits together
The overall score (0–100) is the sum of the category scores, scaled to 100. Each category has a cap (maximum points it can contribute). The five base caps add up to 100, so on a typical scan each cap is that percent share of the total. The WordPress category (cap 8) is conditional — it only applies when we detect WordPress on the scanned site, in which case the total is normalized so a perfect score is still 100.
| Category | Cap (weight) |
|---|---|
| TLS & HTTPS | 32 pts |
| Security headers | 33 pts |
| Exposure & hygiene | 18 pts |
| Cookie practices | 5 pts |
| DNS & email signals | 12 pts |
| WordPress | 8 pts |
The five base caps sum to 100. The WordPress cap (8) is added on top only when WordPress is detected; the overall is then normalized so the maximum possible score stays at 100.
For each category we collect the set of finding ids that fired on your scan (each id counts once). We subtract that finding’s penalty from the category cap, then clamp at zero. The category score is that remainder (shown to one decimal when needed). There is no extra multiplier across categories—what you see is transparent addition.
Some findings are informational (for example notes about Cross-Origin-Resource-Policy). They explain context but may carry no penalty, so they do not appear in the tables below.
Labels such as “Good” are coarse buckets for orientation, not precision engineering. Scores move when certificates renew, CDNs change headers, or you ship new config—re-scan after meaningful changes.
Penalties by finding id
Values are points removed from the category cap when that finding is present. The live scan UI and exports attach plain-language risk and fix steps with Copy / Copy all actions; Pro exports still include the same text in JSON, CSV, and PDF.
TLS & HTTPS
| Finding id | Penalty (pts) |
|---|---|
| no_https | 32 |
| tls_handshake_failed | 25 |
| cert_invalid | 20 |
| cert_expired | 18 |
| weak_tls_protocol | 8 |
| http_no_redirect | 7 |
| cert_expiring_soon | 6 |
| tls_legacy_protocol_offered | 6 |
| redirect_not_https | 5 |
| cert_expiring_month | 3 |
| tls_cert_weak_key | 3 |
| tls_weak_cipher_probe_accepted | 3 |
Security headers
| Finding id | Penalty (pts) |
|---|---|
| missing_csp | 10 |
| missing_hsts | 8 |
| missing_xfo | 5 |
| weak_csp | 5 |
| missing_xcto | 4 |
| weak_hsts | 4 |
| csp_report_only_only | 2 |
| csp_unsafe_eval | 2 |
| csp_wildcard_source | 2 |
| hsts_preload_listed_header_drift | 2 |
| missing_referrer_policy | 2 |
| third_party_script_no_sri | 2 |
| coop_unsafe_none | 1 |
| csp_object_src_open | 1 |
| hsts_preload_eligible_not_listed | 1 |
| hsts_preload_hint | 1 |
| hsts_preload_max_age | 1 |
| missing_coop | 1 |
| missing_permissions_policy | 1 |
| csp_missing_script_default | 0 |
| csp_unsafe_inline_script | 0 |
Exposure & hygiene
| Finding id | Penalty (pts) |
|---|---|
| directory_listing_hint | 7 |
| sensitive_path_probe | 5 |
| origin_ip_direct_access | 4 |
| server_banner_version | 3 |
| security_txt_incomplete | 2 |
| security_txt_missing | 2 |
| x_powered_by | 2 |
Cookie practices
| Finding id | Penalty (pts) |
|---|---|
| session_cookie_missing_httponly | 2 |
| session_cookie_missing_secure | 2 |
| session_cookie_samesite_none | 1 |
DNS & email signals
| Finding id | Penalty (pts) |
|---|---|
| dns_subdomain_takeover_risk | 10 |
| dns_dmarc_missing | 3 |
| dns_dnssec_validation_failed | 3 |
| dns_spf_missing | 3 |
| dns_subdomain_sensitive | 3 |
| dns_dmarc_policy_none | 2 |
| dns_dnssec_unsigned | 1 |
| domain_very_new | 1 |
| domain_recently_registered | 0 |
WordPress
| Finding id | Penalty (pts) |
|---|---|
| wp_install_accessible | 8 |
| wp_setup_config_accessible | 8 |
| wp_user_enumeration | 4 |
| wp_xmlrpc_enabled | 3 |
| wp_readme_exposed | 2 |
DNS & email authentication (limits)
DMARC on a parent domain is a heuristic when your scan target is a subdomain (for example www); we do not ship a full public-suffix list, so organizational boundaries are approximate.
DKIM is only checked for a few common selector names; many providers use different names—not finding DKIM here does not prove email is unsigned. Treat that finding as a reminder to confirm with your mail stack.
These checks help with spoofing and discovery context; they are not a full mail security audit, inbox placement test, or DMARC report analyzer.
Alignment with common frameworks (informative)
Scorifya does not map to OWASP, NIST, or any control framework line-by-line, and it is not a compliance or certification tool. To reduce “black box” criticism, the checks are informed by themes that often appear in public-web hardening guidance:
- OWASP Top 10 (web) — Transport and cookie issues overlap with exposure of sensitive data and broken access-control themes; CSP and framing headers relate to injection and client-side execution; hygiene signals (banners, probe paths) support attack surface reduction.
- NIST Cybersecurity Framework — TLS and redirects support Protect (communications); headers and cookies support Protect for platforms and data;
security.txtsupports Respond (coordinated disclosure contact); visibility headers support Detect in a narrow, configuration-sense only.
Use Scorifya alongside your own threat model, vendor requirements, and professional assessments—never as a substitute for them.
Rate limits and fair use
Free scans are rate-limited per network and related signals so the service stays fast for everyone. Scorifya Pro removes those caps for subscribers. Details appear in the UI when a limit is hit.
Data retention
What we log and for how long is described in the Privacy Policy. The public tool is built for on-demand checks; historical dashboards would ship with explicit notice.
Example result shape
Successful scans return JSON you can export on Pro. Below is a full-length static example payload (anonymized, not a live scan):
Show sample JSON payload
{
"target": "https://acme-demo.example",
"score": 64,
"label": "Fair",
"summary": "This public hardening check produced a score of 64 (Fair). Scorifya does not perform penetration testing, vulnerability scanning, or compliance certification.",
"categories": [
{
"id": "tls",
"name": "TLS & HTTPS",
"score": 24,
"max": 32,
"summary": "Important transport controls are present, but a few downgrade and policy risks remain."
},
{
"id": "headers",
"name": "Security headers",
"score": 18,
"max": 33,
"summary": "Core headers are partially configured; tightening CSP and framing policy would reduce client-side risk."
},
{
"id": "exposure",
"name": "Exposure & hygiene",
"score": 13,
"max": 18,
"summary": "No critical leaks found, but banner and disclosure posture can be improved."
},
{
"id": "cookies",
"name": "Cookie practices",
"score": 4,
"max": 5,
"summary": "Session cookies are mostly hardened with one cross-site policy issue."
},
{
"id": "dns",
"name": "DNS & email signals",
"score": 5,
"max": 12,
"summary": "Mail authentication is partially configured; DMARC policy is not yet enforcing."
}
],
"findings": [
{
"id": "missing_hsts",
"category": "headers",
"severity": "critical",
"title": "Strict-Transport-Security header missing",
"detail": "HTTPS is available, but browsers are not instructed to remember HTTPS for future visits.",
"impact": "First-hop downgrade attacks stay possible when users follow old HTTP links or type a domain manually.",
"pointsDeducted": 12,
"realWorldRisk": "Attackers on hostile networks can keep users on plaintext HTTP and capture session traffic before users notice.",
"likelyAttackScenario": "An attacker on a hostile network path (public Wi‑Fi, compromised router, corporate proxy) downgrades or observes traffic to steal session tokens or credentials.",
"whyAttackersCare": "Sessions are the keys to the kingdom: if attackers can observe or influence login flows, they can impersonate users without ever breaking passwords. Attackers on hostile networks can keep users on plaintext HTTP and capture session traffic before users notice.",
"attackTypes": ["session_theft"],
"fixSteps": [
"Do this first: add Strict-Transport-Security on all HTTPS responses with at least max-age=31536000.",
"After validating subdomains are HTTPS-ready, add includeSubDomains and optionally preload."
],
"codeExamples": [
{
"title": "nginx",
"language": "nginx",
"body": "add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains\" always;"
},
{
"title": "Express (helmet)",
"language": "typescript",
"body": "import helmet from \"helmet\";\napp.use(helmet.hsts({ maxAge: 31_536_000, includeSubDomains: true }));"
}
]
},
{
"id": "weak_csp",
"category": "headers",
"severity": "warning",
"title": "Content-Security-Policy is permissive",
"detail": "script-src still allows unsafe-inline, which weakens script execution controls.",
"impact": "A successful injection bug can execute attacker JavaScript with fewer browser restrictions.",
"pointsDeducted": 5,
"realWorldRisk": "Inline script allowances frequently turn minor template bugs into account-takeover or payment-skimming incidents.",
"likelyAttackScenario": "An attacker exploits an injection bug (or a compromised third-party script) to run JavaScript in your users’ browsers and pivot into account takeover or data exposure.",
"whyAttackersCare": "Browser execution control gaps increase the blast radius of common app bugs—turning “minor” injections into account takeover or payment skimming. Inline script allowances frequently turn minor template bugs into account-takeover or payment-skimming incidents.",
"attackTypes": ["xss"],
"fixSteps": [
"Do this first: remove unsafe-inline from script-src and move inline code to nonce/hash-based patterns.",
"Replace wildcard sources with explicit allowlists for each required host."
]
},
{
"id": "http_no_redirect",
"category": "tls",
"severity": "warning",
"title": "HTTP does not consistently redirect to HTTPS",
"detail": "Port 80 responds without a canonical 301/308 upgrade for all paths.",
"impact": "Users can stay on plaintext connections and send cookies or credentials without transport guarantees.",
"pointsDeducted": 8,
"realWorldRisk": "Even short plaintext windows are enough for interception on public Wi-Fi and shared networks.",
"likelyAttackScenario": "An attacker on a hostile network path (public Wi‑Fi, compromised router, corporate proxy) downgrades or observes traffic to steal session tokens or credentials.",
"whyAttackersCare": "Sessions are the keys to the kingdom: if attackers can observe or influence login flows, they can impersonate users without ever breaking passwords. Even short plaintext windows are enough for interception on public Wi-Fi and shared networks.",
"attackTypes": ["session_theft"],
"fixSteps": [
"Do this first: enforce a 301/308 redirect from every HTTP route to the canonical HTTPS URL.",
"Retest deep paths and query-string URLs to ensure there are no redirect exceptions."
]
},
{
"id": "session_cookie_samesite_missing",
"category": "cookies",
"severity": "warning",
"title": "Session cookie missing SameSite attribute",
"detail": "At least one session-like cookie did not declare SameSite.",
"impact": "Cross-site requests are more likely to include session cookies, increasing CSRF exposure.",
"pointsDeducted": 1,
"realWorldRisk": "Attackers can abuse authenticated browser state from another origin if CSRF controls are weak.",
"likelyAttackScenario": "An attacker on a hostile network path (public Wi‑Fi, compromised router, corporate proxy) downgrades or observes traffic to steal session tokens or credentials.",
"whyAttackersCare": "Sessions are the keys to the kingdom: if attackers can observe or influence login flows, they can impersonate users without ever breaking passwords. Attackers can abuse authenticated browser state from another origin if CSRF controls are weak.",
"attackTypes": ["session_theft"],
"fixSteps": [
"Do this first: set SameSite=Lax for session cookies unless a cross-site flow requires None.",
"If cross-site cookies are required, use SameSite=None; Secure and keep CSRF tokens enforced."
]
},
{
"id": "dns_dmarc_policy_none",
"category": "dns",
"severity": "info",
"title": "DMARC policy is monitor-only (p=none)",
"detail": "DMARC records are present but not enforcing quarantine/reject.",
"impact": "You receive reporting visibility but spoofed mail can still be delivered in many cases.",
"pointsDeducted": 4,
"realWorldRisk": "Brand impersonation remains practical while policy stays monitor-only.",
"likelyAttackScenario": "An attacker spoofs email that appears to come from your domain to phish credentials, reset passwords, or deliver malware.",
"whyAttackersCare": "Brand trust is a high-leverage attack surface: successful spoofing drives phishing and fraud at scale. Brand impersonation remains practical while policy stays monitor-only.",
"attackTypes": ["spoofing"],
"fixSteps": [
"Do this first: review aggregate DMARC reports to confirm valid senders and alignment.",
"Move from p=none to p=quarantine, then p=reject once mail sources are clean."
]
},
{
"id": "corp_cross_origin",
"category": "headers",
"severity": "info",
"title": "Cross-Origin-Resource-Policy allows cross-origin embedding",
"detail": "CORP is set to cross-origin on HTML responses.",
"impact": "Broad embedding is allowed; this may be intentional for public assets but risky for sensitive pages.",
"realWorldRisk": "If sensitive responses are embeddable across origins, browser isolation assumptions can break.",
"likelyAttackScenario": "An attacker exploits an injection bug (or a compromised third-party script) to run JavaScript in your users’ browsers and pivot into account takeover or data exposure.",
"whyAttackersCare": "Browser execution control gaps increase the blast radius of common app bugs—turning “minor” injections into account takeover or payment skimming. If sensitive responses are embeddable across origins, browser isolation assumptions can break.",
"attackTypes": ["xss"],
"fixSteps": [
"Do this first: confirm whether this response should be embeddable by third-party origins.",
"If not intentional, change CORP to same-origin or same-site and retest integration paths."
]
}
],
"technical": {
"final_url": "https://acme-demo.example/",
"http_status": "200",
"redirect_chain": "http://acme-demo.example -> https://acme-demo.example/",
"tls_protocol": "TLSv1.3",
"tls_cipher": "TLS_AES_256_GCM_SHA384",
"tls_valid_to": "2026-10-02T12:00:00.000Z",
"hsts": "missing",
"csp": "present (includes unsafe-inline)",
"x_frame_options": "SAMEORIGIN",
"x_content_type_options": "nosniff",
"referrer_policy": "strict-origin-when-cross-origin",
"dns_spf": "present",
"dns_dmarc": "present (p=none)",
"dns_dkim": "not found (common selectors)",
"security_txt": "present",
"security_txt_expires": "not_set",
"security_txt_canonical": "not_set",
"robots_txt": "present",
"robots_txt_hints": "sitemap",
"dns_caa_present": "yes",
"dns_mta_sts": "not_found",
"dns_tls_rpt": "not_found",
"dns_bimi": "not_found",
"tls_view_tls12_only_protocol": "TLSv1.2",
"tls_curated_weak_cipher_probe_hits": "none"
}
}