Skip to content
RU

Methodology · Open formula

Security Grade methodology v1.2

Open 0–100 formula: four weighted categories, and a composite score under it.

TL;DR. The Security Grade of /security (v1.2) is a weighted average of four categories, each taken as a share of its own maximum: security headers 60 %, HTTPS 20 %, cookies 10 %, information disclosure 10 %. The 0–100 result becomes a letter: A+ from 90, A from 80, B from 70, C from 55, D from 35, F below. The same score and letter are returned by the API (/api/v4/security). Under the grade /security shows a second number — the composite score over 9 categories; it is computed differently and described below. Engines: src/security.php, src/security-headers.php, src/security-composite.php.
Headers60%HTTPS20%Cookies10%Disclosure10%
Changelog. v1.2 (2026-10-05) — headers are taken from the final response after redirects (previously from the first one); cookies of the final page always count, those of intermediate redirects only from the same site; deletions are not counted. v1.1 (2026-10-05) — the formula did not change; its description did. Since publication this page had described a formula the engine never computed: not a sum of five categories out of 55 points but a weighted average of four categories (60/20/10/10) on 0–100; twelve headers with weights of their own (HSTS, CSP and the Server exposure row 15 each…), not the Health Score table; HSTS preload earns 2 points inside HTTPS, not 2 of 10 in an HSTS block; .git/.env/debug paths are not checked; letters are A+ from 90, A from 80, B from 70, C from 55, D from 35, not 50/45/38/30/20 of 55. The composite score — on /security since 2026-05-26 — is described for the first time. Code changes since publication that move points: 2026-08-08 the CSP row is graded by script-src (default-src) only and a nonce or hash makes 'unsafe-inline' inert; 2026-10-04 X-Frame-Options is also earned by a restrictive frame-ancestors of any enforced CSP header (Report-Only does not count). 2026-05-25 made the HSTS preload-list lookup run, but in the headers category it is shown, not scored. v1.0 (2026-05-05) — first publication.

The formula

score = round(60·H/100 + 20·T/Tmax + 10·C/Cmax + 10·D/Dmax)

H — the headers category (0–100), T — HTTPS, C — cookies, D — information disclosure, each divided by its own maximum. All four are always computed.

1. Security headers — 60 %

12 rows worth 110 points; the category is round(earned / 110 × 100). Partial points are the engine's weight × factor, rounded down. An absent header earns 0 unless its row says otherwise.

Header — what earns whatMax
Strict-Transport-Security: max-age ≥ 31536000 — 15; shorter max-age — 7; present with max-age=0 or without max-age — 4; absent — 015
Content-Security-Policy, by script-src (or default-src): no findings — 15; 'unsafe-eval' or an http: source — 10; 'unsafe-inline' without nonce/hash, or * — 6; neither directive — 615
X-Frame-Options DENY/SAMEORIGIN or a restrictive CSP frame-ancestors — 10; another value — 510
X-Content-Type-Options: nosniff — 10; another value — 310
Referrer-Policy: no-referrer, strict-origin(-when-cross-origin), same-origin, origin(-when-cross-origin), no-referrer-when-downgrade — 8; unsafe-url — 2; another value — 48
Permissions-Policy: any value8
X-XSS-Protection: 1… — 5; 0 with a CSP — 5, without — 2; another value — 1; absent with a CSP — 3, without — 05
Cross-Origin-Opener-Policy: same-origin(-allow-popups) — 7; another value — 37
Cross-Origin-Resource-Policy: same-origin, same-site, cross-origin — 7; another value — 37
Cross-Origin-Embedder-Policy: require-corp, credentialless — 6; another value — 36
X-DNS-Prefetch-Control: off — 4; another value or absent — 24
Server exposure: no Server with a version (x.y) and no X-Powered-By — 15; otherwise — 615

Headers — here and in category 4 — are read from the final response: the scan follows redirects (up to 5) and grades the page it lands on, not the redirect; interim 1xx responses (100 Continue, 103 Early Hints) are skipped. The HSTS preload status shown next to HSTS is information here; it is scored in category 2.

2. HTTPS — 20 %

  • 5 — the final URL is HTTPS
  • 5 — http:// on port 80 answers 3xx to an https:// address; 3 if port 80 does not answer and the site is on HTTPS; 0 otherwise
  • 2 — the domain is in the HSTS preload list (hstspreload.org); 1 if pending; 0 if not listed or the lookup failed. This row exists only for an HTTPS site, so the category maximum is 12 over HTTPS and 10 without it

3. Cookies — 10 %

  • 4 — every cookie has Secure (one without it — 0)
  • 3 — every cookie has HttpOnly; 1 if any lacks it
  • 3 — every cookie has SameSite (any value); 1 if any lacks it

No cookies in the responses — 10 of 10. The final page's cookies always count, whatever domain the redirects ended on. Cookies of intermediate redirects count when the redirect is on the scanned site — its host, with or without www, and its subdomains: the browser stores them too. A cookie another domain sets on the way (an SSO or CDN host) and a deletion line (Max-Age ≤ 0, or Expires in the past when there is no Max-Age) are not counted. A flag is looked for as a word anywhere in the Set-Cookie line.

4. Information disclosure — 10 %

  • 4 — no Server header; 3 if it names the server without a version; 0 with a version
  • 3 — no X-Powered-By
  • 3 — no X-AspNet-Version / X-AspNetMvc-Version

Grade letter mapping

Security Grade, 0–100

ScoreGrade
90–100A+
80–89A
70–79B
55–69C
35–54D
0–34F

The composite score under the grade

/security also shows a «Composite security score» (0–100, A–F). It takes the same checks, buckets them by name into 9 categories and gives each category its maximum × the share of its checks that passed (a warning is not a pass). Only categories that received at least one check count, and the sum is scaled to 100: round(Σ round(max × passed/total) / Σ max × 100). Letters: A from 90, B from 75, C from 60, D from 40, F below.

Category — what falls into it todayMax
Transport: HTTPS, HSTS, redirect, preload25
CSP20
Other headers (10 of the 12 rows of category 1)15
Cookies10
«Exposed»: X-Powered-By and the ASP.NET version — when exposed10
Disclosure: Server; X-Powered-By and ASP.NET — when hidden5
CORS5
SRI5
Mixed content5

The report has no CORS, SRI or mixed-content checks, so those three categories never count today. Because the bucket is chosen by the check's name, an exposed X-Powered-By or ASP.NET version lands in «exposed», while the hidden ones count under «disclosure».

Composite score, 0–100

Where else a «security» grade appears

The Security badge (/badges), the public report /report/{domain}/security and the «Verified by Enterno» catalog use a light formula from one HEAD request: points for each present header — HSTS 20, CSP 20, X-Frame-Options 12, X-Content-Type-Options 12, Referrer-Policy 12, Permissions-Policy 12 — and 12 more when all six are present; capped at 100. Badge letters: A from 90, B from 80, C from 70, D from 60, E from 50, F below.

The MCP tool check_security returns category 1 only (headers, 0–100) with its own letter: A from 90, B from 75, C from 55, D from 35, F below.

Versioning

Current version — v1.2, updated . Every change to the published formula — the weights or their description — is a new version with a line in the changelog above.

Run a security scan →

Calculator

Set what the site serves — get the grade and the composite score by the same rules as the /security check. The calculator makes no requests.

1. Security headers
2. HTTPS
3. Cookies
Security Grade
--
A
Composite score
--
A


  
Check my site →