Year 1 / Module 4 The web as an interaction platform / Unit 9 / Security where the browser parses stored content as code

Security where the browser parses stored content as code

HCI1104 · Unit 9 of 10

Because the browser executes stored content as code, a programmable document carries a security surface that belongs to the designer as much as to the backend, and defence is an output-context decision rather than an input filter.

Security where the browser parses stored content as code

A page is a program the browser agrees to run. It parses a document, and whatever is valid syntax where it appears becomes behaviour. When a site writes a stored string back into a document, the choices separating text from code are taken by whoever chose the element and the context. The security surface belongs to the designer, and the defence is an output-context decision rather than an input filter. The strongest counter to this unit's thesis is that the decision is often not the author's to make. Frameworks escape by default, and Ren and Yue (2024) found most sites without a policy could deploy a safe one. The remaining bugs sit where a framework leaves an escape hatch. The eight units before it asked what the page must do for a reader. This one asks what it can do to the reader, and where the decision sits that prevents it.

The model is isolation, and the root cause is a string returned as code

User agents divide content by origin, and restrict how content from one origin interacts with another, so a document served by a hostile machine cannot read documents held by an honest one (Barth, 2011). The origin is defined by scheme, host and port, not by a name or a path.

Isolation does not cover the string the application hands back. Di Lucca and colleagues (2004) traced cross-site scripting to one failure: an application returns user input to the browser unchecked, so a string containing code runs in another reader's browser. The maintained rule set starts from the same premise. Every variable must be validated and then encoded for the place it is written into, a condition its authors call perfect injection resistance (OWASP Foundation, n.d.). Both are statements about where a string ends up, not where it came from.

Defence is decided by the parser that receives the value

The operational form of the thesis is a table of contexts: browsers parse HTML, JavaScript, URLs and CSS by different rules, so encoding must match the parser the value is handed to, and the same string can be safe in one context and executable in another (OWASP Foundation, n.d.).

Work one value in three contexts. A search term the reader typed, tea & coffee, is rendered as text in the results heading with no special escape beyond the ampersand. The same value placed inside an HTML attribute needs its quotes escaped. Inside a URL query it needs percent-encoding, and inside a script block it needs JavaScript escaping. Each parser delimits differently, so the escape that is correct in one context leaves the value broken or executable in another. That is why the maintained rule is to encode for the destination rather than filter at the source.

Klein and Johns (2024) show the principle at the level of the sanitiser. A server-side sanitiser must parse markup to judge whether it is dangerous. Where its parser disagrees with the browser's, markup it judges benign can become a payload. Testing eleven sanitisers across five programming languages with generated hard-to-parse fragments, they bypassed all but two. The defence must agree with the parser that consumes its output, not filter the strings that arrive.

Content becomes code without a script tag

The strongest form of the argument is an attack carrying no script. Khodayari and Pellegrino (2023) systematise DOM clobbering, in which seemingly benign HTML overwrites a JavaScript variable through an unforeseen interaction with the runtime. Across nineteen browsers they found 31,400 markups using five techniques. Their detector found 9,467 vulnerable data flows across 491 of the Tranco top 5,000 sites. Element and attribute choice is itself the attack surface, which makes this a design problem.

Work the mechanism on one global. A page's own script expects config to be an object with a url property. An attacker who can store markup adds <form id="config"> holding an <input name="url">. The browser's named-access rule then makes window.config the form and config.url the input, so the script reads an element where it expected a string. Nothing in the stored markup executed, and no policy about script sources could have blocked it.

The designed defences failed at the scale they were deployed

Weichselbaum and colleagues (2016) analysed a corpus of roughly 100 billion pages from over a billion hostnames, covering 1,680,867 hosts and 26,011 content security policies. They found bypasses in 94.72 per cent of those policies. Of them, 75.81 per cent used script whitelists an attacker could bypass, and 99.34 per cent of hosts held a policy offering no benefit against cross-site scripting. Their repair is to replace whitelists with nonces, adopted as the strict-dynamic keyword.

Two defence mechanisms can also obstruct each other, as Some, Bielova and Rezk (2017) show. They analysed 1 million pages from 10,000 highly ranked sites. They reported at least 31.1 per cent of pages with a policy vulnerable to a violation caused by the same-origin rules rather than an attack, falling to 23.5 per cent in nested contexts.

The failure belongs to the toolchain as well as the policy. Ren and Yue (2024) instrumented a browser across the Tranco top 100,000 sites, inserting a policy to record the violations it caused. They found builder-generated sites more likely to carry third-party scripts that break a policy. Against that, Pan and colleagues (2016) show a policy can be generated rather than hand-written. Fewer than 0.002 per cent of the Alexa top million sites enabled one, so their system learned templates per site and enforced a generated policy by rewriting pages in flight. The question is not whether the mechanism works but who can be relied on to deploy it.

The surface extends to what the page loads

A document inherits the trustworthiness of its least trustworthy inclusion. The Subresource Integrity specification defines an integrity attribute carrying a cryptographic hash, so a user agent verifies a fetched resource before executing it. Its rationale is that transport security authenticates the server but not the content (W3C, 2016). Duan and colleagues (2021) report 339 previously unknown malicious packages in the dependency registries of interpreted languages. Maintainers confirmed 278 of them, 82 per cent, and three had more than 100,000 downloads.

The consequence is sharpest where confidentiality is the service: Puhtila, Carlsson and Rauti (2023) found that 95.5 per cent of the women's shelter websites they studied leaked visitors' personal data, including IP addresses and device identifiers. The transport floor has risen without becoming uniform. Kerschbaumer and colleagues (2025) analysed data from more than 140 million Firefox release users, and found 92.1 per cent of top-level connections secure, against about 30 per cent a decade earlier. The rate ranged from 98.0 per cent in Denmark to 51.2 per cent in Sudan.

Contested question: where the defence belongs, and who is accountable for it?

One position treats the policy mechanism as the right layer, and its failure as a repair job: Weichselbaum and colleagues (2016) proposed nonces through strict-dynamic, and Pan and colleagues (2016) show strict policies generated without server changes. The other position holds that the parser is the right place. OWASP Foundation (n.d.) argues encoding must match the context, and Klein and Johns (2024) show sanitisers fail because they disagree with the browser about the same markup. What would settle it is a matched field comparison between sites enforcing a generated nonce-based policy and sites relying on contextual output encoding, with escape hatches instrumented in both arms.

A second dispute is about agency. For the platform and toolchain: frameworks that escape by default have fewer injection bugs, and builder platforms could ship strict policies by default, so the omission looks like a matter of defaults. For the author: frameworks reduce bugs and then provide escape hatches (OWASP Foundation, n.d.). DOM clobbering arises from element choices no policy about script sources can prevent (Khodayari and Pellegrino, 2023). What would settle it is a longitudinal comparison of injection incidents between applications whose framework enforces contextual encoding by construction and applications whose templates are hand-written, with escape-hatch use recorded in both arms.

While the question is open, a designer should encode at the point of output and treat the framework's escape hatches as the risk register. Pass a stored string through the encoder that matches its destination, and never assemble markup from stored text. Keep a policy whose scripts are named by nonce, and check that the sanitiser parses markup the way the browser does.

Where the argument is heading

Three named directions are visible. The defence is migrating towards agreement between parsers, the object of study Klein and Johns (2024) propose in place of payload patterns. The remaining risk is moving up from the network into the document, since Kerschbaumer and colleagues (2025) place the transport floor near ninety per cent while Khodayari and Pellegrino (2023) find executable behaviour arising from element and attribute choices alone. The next contract is likely to have content carry a statement about itself, as a hash, a nonce or a declared trust relationship. The designer is the one who writes it.

The sources this unit rests on

  • Weichselbaum, L., Spagnuolo, M., Lekies, S. and Janc, A. (2016). CSP Is Dead, Long Live CSP! On the Insecurity of Whitelists and the Future of Content Security Policy. Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security. doi:10.1145/2976749.2978363 A corpus of roughly 100 billion pages, covering 26,011 distinct policies, showed bypasses in 94.72 per cent of them and no benefit against cross-site scripting for 99.34 per cent of hosts. It measures a defence that failed at the scale it was deployed.
  • Pan, X., Cao, Y., Liu, S., Zhou, Y., Chen, Y. and Zhou, T. (2016). CSPAutoGen: Black-box Enforcement of Content Security Policy upon Real-world Websites. Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security. doi:10.1145/2976749.2978384 Reporting fewer than 0.002 per cent of the Alexa top million sites with a policy, the authors generate and enforce strict policies by rewriting pages in flight, resisting every attack they tested. It is the constructive counterpoint to the policy critique.
  • Some, D. F., Bielova, N. and Rezk, T. (2017). On the Content Security Policy Violations due to the Same-Origin Policy. Proceedings of the 26th International Conference on World Wide Web. doi:10.1145/3038912.3052634 Analysing 1 million pages from 10,000 highly ranked sites, the authors found at least 31.1 per cent of policy-bearing pages vulnerable to violations caused by the same-origin rules, 23.5 per cent in nested contexts. It shows two security mechanisms obstructing each other.
  • Ren, M. and Yue, C. (2024). Content Security Policy Deployment Issues Related to Third-party Scripts among Builder-generated Websites and Other Websites. 2024 IEEE International Performance, Computing, and Communications Conference (IPCCC). doi:10.1109/ipccc59868.2024.10850449 An instrumented browser across the Tranco top 100,000 sites showed builder-generated sites more likely to carry third-party scripts that cause policy deployment problems. Security posture is thus a property of the toolchain, not of a single page.
  • Khodayari, S. and Pellegrino, G. (2023). It's (DOM) Clobbering Time: Attack Techniques, Prevalence, and Defenses. 2023 IEEE Symposium on Security and Privacy (SP). doi:10.1109/sp46215.2023.10179403 Across nineteen browsers, 31,400 markups using five techniques overwrite JavaScript variables, and 9,467 vulnerable data flows appeared across 491 of the Tranco top 5,000 sites. The attack needs no script tag, which is what makes it the strongest support for the thesis.
  • Klein, D. and Johns, M. (2024). Parse Me, Baby, One More Time: Bypassing HTML Sanitizer via Parsing Differentials. 2024 IEEE Symposium on Security and Privacy (SP). doi:10.1109/sp54263.2024.00177 Generated hard-to-parse markups bypassed nine of the eleven sanitisers tested across five programming languages, showing a sanitiser can turn benign markup into a payload where its parser disagrees with the browser. It puts agreement between parsers at the centre of the defence.
  • Di Lucca, G. A., Fasolino, A. R., Mastoianni, M. and Tramontana, P. (2004). Identifying cross site scripting vulnerabilities in Web applications. Proceedings of the Sixth IEEE International Workshop on Web Site Evolution (WSE 2004). doi:10.1109/wse.2004.10013 Static analysis of server pages combined with dynamic testing located the failure in an application returning unvalidated input to the browser. It is the root-cause statement the output-context rule answers.
  • Barth, A. (2011). The Web Origin Concept. IETF RFC 6454, December 2011. doi:10.17487/rfc6454 The origin is defined, with the rule by which user agents divide content and the conditions under which content from one origin may interact with another. It is normative rather than empirical, and supplies the boundary every claim here depends on.
  • OWASP Foundation (n.d.). Cross Site Scripting Prevention Cheat Sheet. OWASP Cheat Sheet Series. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html Variables must be validated and then encoded for the context they are written into; the sheet catalogues HTML, attribute, URL, JavaScript and CSS contexts and notes that frameworks still provide escape hatches. It states the unit's design claim in operational form.
  • Duan, R., Alrawi, O., Kasturi, R. P., Elder, R., Saltaformaggio, B. and Lee, W. (2021). Towards Measuring Supply Chain Attacks on Package Managers for Interpreted Languages. Proceedings 2021 Network and Distributed System Security Symposium. doi:10.14722/ndss.2021.23055 Program analysis of package registries found 339 previously unknown malicious packages, 278 of them (82 per cent) confirmed by maintainers, three with more than 100,000 downloads. It extends the security surface to the dependencies an author includes.
  • W3C (2016). Subresource Integrity. W3C Recommendation, 23 June 2016. https://www.w3.org/TR/2016/REC-SRI-20160623/ An integrity attribute carrying a cryptographic hash lets a user agent verify a fetched resource before executing it, since transport security authenticates the server but not the content. The dated Recommendation URL is cited because the undated one now serves the Level 2 Working Draft of 20 March 2026.
  • Puhtila, P., Carlsson, R. and Rauti, S. (2023). Privacy Risks of Third-Party Services on Women's Shelter Websites. 2023 16th International Conference on Security of Information and Networks (SIN). doi:10.1109/sin60469.2023.10474822 On 95.5 per cent of the women's shelter websites studied, third-party requests leaked visitors' personal data, including IP addresses and device identifiers. It makes an embedded service a confidentiality decision.
  • Kerschbaumer, C., Braun, F., Friedberger, S. and Juergens, M. (2025). The State of https Adoption on the Web. Proceedings 2025 Workshop on Measurements, Attacks, and Defenses for the Web. doi:10.14722/madweb.2025.23001 Data from more than 140 million Firefox release users show 92.1 per cent of top-level connections secure, against about 30 per cent a decade earlier, ranging from 98.0 per cent in Denmark to 51.2 per cent in Sudan. It fixes the transport baseline beneath the unit's argument.

Check your understanding & apply it · 4 questions, 1 essay

1The unit argues that defence belongs to the output context rather than to an input filter. Which finding best supports that claim?
2Which result shows that executable behaviour can arise from an ordinary element choice with no script tag present?
3A developer stores a reader's display name and writes it into three places: as text in a heading, inside an HTML attribute, and inside a URL query. What defence does the unit's account prescribe for that value?
4Which result is the strongest counter-argument to the unit's claim that the security surface is primarily the designer's responsibility?
5Essay Choose one real web feature you could design: a comment thread, a user profile, a search results page, or a page carrying a third-party embed. Write a short security argument in three parts. First, identify one place where stored content is written back into a document, and state which parser receives the value and what that implies for encoding. Second, choose the defence you would rely on, such as encoding for the output context, a nonce-based policy, or an integrity hash on an included dependency, and give both the evidence that it works and the evidence that it fails. Third, answer the unit's contested question for your case: does responsibility for the outcome sit with you as the designer or with the toolchain, and what evidence would change your mind? Cite at least four sources from this unit, including at least one that limits or contradicts your position.