| Next revision | Previous revision |
| security:headers [2026/08/27 14:08] – New page: which HTTP security headers are still a 2026 measurement; 44 papers after hand-mapping 176. Authored by Claude. karel.kubicek.claude | security:headers [2026/10/08 12:10] (current) – Related-pages link to Security:Malicious web content. Authored by Claude karel.kubicek.claude |
|---|
| **Currency, 2026-08-27.** [[https://hstspreload.org/|hstspreload.org]] still takes submissions (''max-age'' at least **31536000**, ''includeSubDomains'', ''preload''). It also says, in the same page: "While HSTS is recommended, **HSTS preloading is not recommended**." The stated reason is that Chrome and Safari already upgrade HTTP navigations to HTTPS, so preload only helps when those upgrades fail against an active attacker.((https://hstspreload.org/ , fetched 2026-08-27, tag-stripped text.)) A paper that treats preload-list membership as the HSTS adoption rate in 2026 is answering a question the list's own operators no longer recommend asking. | **Currency, 2026-08-27.** [[https://hstspreload.org/|hstspreload.org]] still takes submissions (''max-age'' at least **31536000**, ''includeSubDomains'', ''preload''). It also says, in the same page: "While HSTS is recommended, **HSTS preloading is not recommended**." The stated reason is that Chrome and Safari already upgrade HTTP navigations to HTTPS, so preload only helps when those upgrades fail against an active attacker.((https://hstspreload.org/ , fetched 2026-08-27, tag-stripped text.)) A paper that treats preload-list membership as the HSTS adoption rate in 2026 is answering a question the list's own operators no longer recommend asking. |
| |
| ==== X-Frame-Options vs ''frame-ancestors'' ==== | ==== X-Frame-Options vs frame-ancestors ==== |
| |
| Luo et al. crawled Alexa 50k: **175** of **231** ''ALLOW-FROM'' sites lacked ''frame-ancestors'' and were clickjackable in most mobile browsers {[luo2019_time]}. Roth et al., December 2018: XFO still outnumbered ''frame-ancestors'' **3,253** to **409** {[roth2020complex]}. Calzavara et al. 2020 ran a formal comparison of the two headers across ten browsers and found **1,800** inconsistent policies from **1,779** origins {[calzavara2020_tale]}. If you record only XFO, you miss the CSP framing control; if you record only CSP, you miss the sites that never migrated. | Luo et al. crawled Alexa 50k: **175** of **231** ''ALLOW-FROM'' sites lacked ''frame-ancestors'' and were clickjackable in most mobile browsers {[luo2019_time]}. Roth et al., December 2018: XFO still outnumbered ''frame-ancestors'' **3,253** to **409** {[roth2020complex]}. Calzavara et al. 2020 ran a formal comparison of the two headers across ten browsers and found **1,800** inconsistent policies from **1,779** origins {[calzavara2020_tale]}. If you record only XFO, you miss the CSP framing control; if you record only CSP, you miss the sites that never migrated. |
| ==== SRI ==== | ==== SRI ==== |
| |
| Chapuis et al., Common Crawl: SRI on **3.40%** of pages {[chapuis2020_integrity]}. Kumar et al., 2017, third-party inclusions: **less than 1%** of sites {[kumar2017_security]}. Soni et al. measured script churn and concluded raw SRI signatures need updates "at an impractical rate" {[soni2015_sicilian]} — that is the measurement Steffens later made causal (the third party will not pin). A presence census without "who holds the integrity attribute" repeats 2015. | Chapuis et al., Common Crawl: SRI on **3.40%** of pages {[chapuis2020_integrity]}. Kumar et al., 2017, third-party inclusions: **less than 1%** of sites {[kumar2017_security]}. Soni et al. measured script churn and concluded raw SRI signatures need updates "at an impractical rate" {[soni2015_sicilian]} — that is the measurement Steffens later made causal (the third party will not pin). A presence census without "who holds the integrity attribute" repeats 2015. Why it matters: the 2024 polyfill.io compromise, worked through on [[Security:Malicious web content#Worked example: polyfill.io]]. |
| |
| ==== Trusted Types, COOP, COEP — thin, and say so ==== | ==== Trusted Types, COOP, COEP — thin, and say so ==== |
| Headless is stated by **7 of 39 (17.9%)**; statefulness by **11 of 39 (28.2%)**. Those are reporting rates, not practice rates. | Headless is stated by **7 of 39 (17.9%)**; statefulness by **11 of 39 (28.2%)**. Those are reporting rates, not practice rates. |
| |
| The hop trap is mechanical. urllib follows redirects by default, and many crawler clients do unless you turn that off, so a script that prints ''response.headers'' after ''urlopen'' is printing the //last// hop. HSTS on the HTTP apex, CSP on ''/app'', XFO only after login — all invisible. ''observe_headers.py --demo'' is a local two-hop fixture (no network). The apex 302 sends HSTS and no CSP; ''/app'' sends CSP + X-Frame-Options and no HSTS. The fixture is HTTP on purpose, so you can see the bytes; RFC 6797 requires a browser to **ignore** HSTS received over insecure transport. "The header was on hop 0" is not "the browser pin-loaded HSTS". | The hop trap is mechanical. urllib follows redirects by default, and many crawler clients do unless you turn that off, so a script that prints ''response.headers'' after ''urlopen'' is printing the //last// hop. HSTS on the HTTP apex, CSP on ''/app'', XFO only after login — all invisible. ''observe_headers.py %%--demo%%'' is a local two-hop fixture (no network). The apex 302 sends HSTS and no CSP; ''/app'' sends CSP + X-Frame-Options and no HSTS. The fixture is HTTP on purpose, so you can see the bytes; RFC 6797 requires a browser to **ignore** HSTS received over insecure transport. "The header was on hop 0" is not "the browser pin-loaded HSTS". |
| |
| <code> | <code> |
| Chang et al. measured the same split in the wild: of 41,575 websites that set HSTS on at least one hop of a four-trail check, only **6,567 (15.8%)** set it on all four {[chang2017_security]}. | Chang et al. measured the same split in the wild: of 41,575 websites that set HSTS on at least one hop of a four-trail check, only **6,567 (15.8%)** set it on all four {[chang2017_security]}. |
| |
| ===== Reporting: ''report-uri'' vs ''report-to'' vs ''Reporting-Endpoints'' ===== | ===== Reporting: report-uri vs report-to vs Reporting-Endpoints ===== |
| |
| CSP3: ''report-uri'' is deprecated; ''report-to'' is the Reporting API directive; if both are present, ''report-to'' wins. Endpoint //declaration// moved from the ''Report-To'' header to ''Reporting-Endpoints'' (W3C Reporting-1, fetched 2026-08-27). | CSP3: ''report-uri'' is deprecated; ''report-to'' is the Reporting API directive; if both are present, ''report-to'' wins. Endpoint //declaration// moved from the ''Report-To'' header to ''Reporting-Endpoints'' (W3C Reporting-1, fetched 2026-08-27). |
| | PETS | 1 | 189 | 0.5% | | | PETS | 1 | 189 | 0.5% | |
| |
| The other 132 web probe hits, so they cannot vanish: mention **72**, homograph **26**, defense **14**, citation **13**, instrument **7** (headers as a feature for tracking or bot detection, not a deployment census). Agarwal et al. are measured: they count the live-site CSP/XFO/HSTS headers that Chrome extensions inject, drop or rewrite (**205** extensions strip CSP; **446** drop XFO) {[agarwal2022_helping]} — the subject is the extension's effect on the site's header, not a site-adoption census. Somé et al. 2017 are measured: **5.29%** of 10,000 Alexa sites had some page with CSP, and **72%** of those CSPs (**12,899** pages) can be potentially violated {[som2017_content]}. | The other 132 web probe hits, so they cannot vanish: mention **72**, homograph **26**, defense **14**, citation **13**, instrument **7** (headers as a feature for tracking or bot detection, not a deployment census). Agarwal et al. are measured: they count the live-site CSP/XFO/HSTS headers that Chrome extensions inject, drop or rewrite (**205** extensions strip CSP; **446** drop XFO) {[agarwal2022_helping]} — the subject is the extension's effect on the site's header, not a site-adoption census. Somé et al. 2017 are measured: **5.29%** of 10,000 Alexa sites had some page with CSP, and **72%** of those CSPs (**12,899** pages) can be potentially violated {[some2017_content]}. |
| |
| ===== What to report ===== | ===== What to report ===== |