The policy allows inline styles
Updated
What this check looks for
Allowing inline CSS in a Content Security Policy lets injected styles leak page data and disguise the page. Why ad code often needs it, and stronger options.
In a report, this finding reads as follows, with each ‹…› filled in from what that scan observed:
The policy lets the page apply CSS written directly into the HTML:
<style>blocks,styleattributes, or both. An injected style cannot run code, but it can still read parts of the page and change what a visitor sees.
Why it matters
If an attacker can get markup into a page — a comment, a profile field, a reflected parameter — inline CSS lets them act on it even with scripts blocked: selectors can leak a token or form value a character at a time through background-image requests, and repositioned content can trick a visitor into clicking or typing in the wrong place.
When the check passes, your report says: “The policy blocks inline styles”.
What it costs your score
When this check fails it removes 4 points from your Web security score, before the status, confidence and repeat multipliers are applied. Web security carries a weight of 8 in the overall score.
It shares the web-security.csp family ceiling of 30 points: however many findings that family produces, together they cannot remove more than that from Web security. One underlying problem showing up in several places is still one problem.
- Severity
- low
- Default confidence
- confirmed
- Status when triggered
- warn
- Deduction
- 4 points
- Family cap
- web-security.csp · 30
- Category
- Web security
- Module
- Web security headers
- Fix owned by
- user
- In the ruleset since
- 2026.10
How to fix it
Allow your own inline styles by nonce or hash — not by 'unsafe-inline', and not by leaving styles ungoverned — or narrow the exception to style attributes.
Inline CSS lets an injected style read values off the page and disguise it, even when scripts are blocked.
If the policy sets no
style-srcand nodefault-src, nothing governs styles: adddefault-src 'self'or astyle-srcof your own first.Put a per-response nonce on each
<style>element you serve and list it instyle-src; hash any fixed block instead if the page is static.For a few fixed
styleattributes, list their hashes with'unsafe-hashes', or move them into a stylesheet.If ad code or a framework sets style attributes you cannot control, narrow rather than remove: a nonce in
style-src, plusstyle-src-attr 'unsafe-inline'. This rule still reports that, because attributes stay open; it is a smaller exception, not a fix.Test with an ad-serving page open in report-only mode first: a blocked style breaks the layout without an error a visitor would see.
How to confirm it worked
curl -sSI https://‹host›/ | grep -i content-security-policy
Content-Security-Policy: default-src 'self'; style-src 'self' 'nonce-{{RANDOM}}'; object-src 'none'; base-uri 'none'A named slot like ‹domain› — and the braces left in the configuration below — is filled in with your own values when this rule appears on a report.
Remediation by platform
add_header Content-Security-Policy "default-src 'self'; style-src 'self' 'nonce-‹random›'; object-src 'none'; base-uri 'none'" always;<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; style-src 'self' 'nonce-‹random›'; object-src 'none'; base-uri 'none'"
</IfModule>header {
Content-Security-Policy "default-src 'self'; style-src 'self' 'nonce-‹random›'; object-src 'none'; base-uri 'none'"
}Rules → Overview → Create rule → Response Header Transform Rule → Set static → Content-Security-Policy = default-src 'self'; style-src 'self' 'nonce-‹random›'; object-src 'none'; base-uri 'none'
(Dashboard path as at 2026-09; Cloudflare reorganised these pages and may again.)The
alwaysflag matters: without it nginx omits the header on error responses, which are exactly the ones an attacker aims for. Note also that anyadd_headerin alocationblock discards everyadd_headerinherited from the server block.Shown because the response identified Apache. Put it in the virtual host rather than .htaccess: .htaccess is re-read on every request, and
Header always setthere runs too late for responses the server generates itself.A Transform Rule adds the header at Cloudflare's edge, so it applies only to responses that reach visitors through Cloudflare. An origin that is reachable directly — by IP, or through a DNS record that is not proxied — still serves the response measured here without it. Setting it at the origin covers both paths.
Technical detail
‹detail›. A policy that sets none of style-src-elem, style-src-attr, style-src or default-src restricts no style at all, so it is reported here as well: an absent directive blocks nothing. Scripts are graded separately, by csp-unsafe-inline and csp-missing; this rule says nothing about whether injected script would run.
The risk is real and smaller than inline script. CSS cannot execute code, but an injected <style> block can use attribute selectors such as input[value^="a"] to make the browser request a different background image for each possible character of a value, which sends a CSRF token or a pre-filled field to the attacker's server piece by piece. Injected CSS can also restyle and reposition the page to overlay a fake form or hide a warning — UI redressing without a frame.
It is also very common, and often not a choice. Advertising code needs it: Google's own AdSense ad unit snippet puts a style attribute on its <ins> element, and ad scripts insert markup carrying style attributes of their own. Some frameworks and component libraries inject <style> elements at runtime. Removing 'unsafe-inline' without a replacement breaks those pages, so this is a low-priority warning rather than a failure.
The stronger options, best first: a per-response nonce on your own <style> elements (style-src 'self' 'nonce-…'), or a hash for a fixed block; 'unsafe-hashes' with the hash of each specific style attribute value you need; and narrowing — a nonce in style-src or style-src-elem while style-src-attr 'unsafe-inline' keeps attributes working. Narrowing still reports here, because attributes stay open, but it closes <style> blocks, which carry the selector attack; an attribute styles only its own element. None of these is always feasible with ads: the markup an ad network inserts is not yours to nonce or hash, and changes without notice. Browser support for style-src-attr, style-src-elem and 'unsafe-hashes' arrived later than for style-src; check current data before relying on one.
Standards and references
Test this on your domain
Run the check that produces this finding, on its own, against any domain.