CSP Bypass Using HTML Injection and Browser Caching: How It Works and How to Defend

A newly discovered cybersecurity technique combines HTML injection, CSS-based nonce leakage, and browser cache manipulation to bypass Content Security Policy (CSP) protections. By extracting nonce values from meta tags and using browser cache behaviors like bfcache and disk cache, attackers can execute malicious scripts with valid CSP nonces. This attack exposes web applications to XSS risks, even when they use proper CSP configurations.

Jul 05, 2025 - 14:09
Updated: 1 month ago
104.2k
CSP Bypass Using HTML Injection and Browser Caching: How It Works and How to Defend

Quick answer: Researchers have described CSP bypasses where an attacker who can inject HTML, but not run script, manages to obtain a valid nonce through browser caching behaviour, then reuses it so injected script is allowed. The defence is to stop HTML injection, avoid caching pages that carry nonces, and use a strict policy.

Key takeaways

  • A nonce-based CSP only works if the nonce is unpredictable and never reusable.
  • HTML injection without script execution is still dangerous when a policy trusts nonces.
  • Caches that store a page with its nonce can make that nonce guessable or reusable. Do not cache nonce pages.
  • Fix the root cause first: encode output and sanitise HTML. CSP is a second layer, not a substitute.
  • Use strict CSP, Trusted Types, base-uri and object-src restrictions together.

What is Content Security Policy?

Content Security Policy (CSP) is an HTTP response header that tells the browser which sources of script, style, images and frames a page may use. Its main job is to limit the damage from cross-site scripting (XSS). A strict, modern policy usually relies on a nonce: a random value generated by the server for each response, sent in the header (script-src 'nonce-abc123') and copied onto every legitimate script tag. The browser runs only scripts that carry the matching nonce. The MDN CSP guide and the OWASP CSP cheat sheet explain the syntax in detail.

Why is HTML injection still a problem under CSP?

With a good CSP, an attacker who injects <script>alert(1)</script> fails, because the tag has no valid nonce. But HTML injection is a wider class of flaw than script injection. An injected tag can still change the page: add a form that posts to another site, change a link, add markup that swallows later content (so-called dangling markup) or influence what the browser stores and reuses. CSP limits scripts; it does not make HTML injection harmless.

How can caching undo a nonce?

The security of a nonce depends on one rule: a nonce must be fresh for every response and must stay unknown to the attacker. Browsers, however, cache pages. The back/forward cache (bfcache) can restore a whole page exactly as it was, and the HTTP disk cache can serve a stored copy of the HTML. If an attacker can make the victim's browser reuse an earlier copy of a page, or can read the markup of a cached copy through injected content, the nonce inside that copy can be learned and then reused in a new injection. In outline, the reported technique combines three ingredients:

  1. An HTML injection point on a page protected by a nonce-based CSP.
  2. A way to leak or recover the nonce value that the page printed, using the injection together with caching behaviour.
  3. A second injection that includes a script tag carrying that same nonce, which the policy now accepts because the nonce matches.

This article deliberately stays at the level of the idea. If you want to study it practically, reproduce it only in your own lab application, with your own browser profile, and read the original researcher's write-up for browser-specific details. Browser versions change behaviour quickly, so a technique that works in one release may be blocked in the next. Testing real third-party sites without written permission is illegal under the IT Act.

How do you defend against it?

ControlWhat it does
Output encoding and sanitisationRemoves the injection point, which is the root cause
Cache-Control: no-store on pages that contain noncesStops disk-cache reuse and reduces bfcache restoration of sensitive pages
Fresh nonce per response from a secure random generatorMakes a leaked value useless on the next load
base-uri 'none' and object-src 'none'Blocks common ways to redirect relative scripts or load plugins
form-action 'self'Prevents injected forms posting data elsewhere
Trusted TypesForces DOM sinks to receive vetted values only
CSP report-only monitoringShows violations before and after changes

What should developers do this week?

  1. List every page that prints a nonce and check its caching headers.
  2. Add no-store to authenticated or sensitive pages that carry nonces, and test that the page still behaves acceptably when users press Back.
  3. Search for every place user input reaches HTML, including rich-text fields, comments and error pages.
  4. Tighten the policy with the directives in the table and turn on reporting.

Common mistakes

  • Treating CSP as the XSS fix instead of a backstop.
  • Re-using one static nonce for all users or all requests.
  • Allowing unsafe-inline alongside nonces and assuming nonces still protect you (browsers ignore it only in certain combinations).
  • Caching full HTML at a CDN without checking whether it contains per-user nonces.

Next steps

Start with the basics of XSS and its prevention in the detailed guide to cross-site scripting. If you want to practise web security in a legal lab, see our web application penetration testing course.

Related reading

Frequently Asked Questions

CSP is a browser-enforced policy sent in an HTTP header that restricts where scripts, styles, frames and other resources can load from. Its main purpose is to reduce the impact of cross-site scripting by blocking unauthorised script execution.

A nonce is a random, single-use value the server generates for each response. It appears in the CSP header and on trusted script tags. The browser only runs scripts whose nonce matches, so an attacker without the value cannot add working scripts.

HTML injection gives the attacker a way to place markup into the page even when script tags are blocked. Combined with a method to learn or reuse the nonce, the injected markup can introduce a script that the policy accepts.

The back/forward cache lets a browser keep a complete page, including its state, in memory so that Back and Forward navigation is instant. A restored page can contain a nonce from an earlier load, which is why caching matters for nonce-based policies.

It helps but is not a full fix. It reduces cache reuse of pages that carry nonces, but the underlying HTML injection must also be removed, and the policy should be hardened with base-uri, object-src and Trusted Types.

Yes. A strict nonce-based or hash-based CSP still blocks most XSS attempts. Treat it as a second layer of defence behind proper output encoding and input handling, and review it as browsers change.

What's Your Reaction?

Like Like 0
Dislike Dislike 0
Love Love 0
Funny Funny 0
Wow Wow 0
Sad Sad 0
Angry Angry 0
Vaishnavi

Vaishnavi is a skilled tech professional at the Ethical Hacking Training Institute in Pune, responsible for managing and optimizing the technical infrastructure that supports advanced cybersecurity education. With deep expertise in network security, backend operations, and system performance, she ensures that practical labs, online modules, and assessments run smoothly and securely. Her behind-the-scenes contributions play a vital role in delivering a seamless and secure learning experience for aspiring ethical hackers.