CSS-37Required
Never read elements through window globals
Find elements only with getElementById or querySelector, never as a property of window or document. Remove or prefix the id and name attributes in any HTML that users supply.
Review by
2027-06-30
How to do it
The browser makes every element with an id a property of window, and some elements with a name too. A comment holding <a id="config" href="https://evil.example/"> then takes the place of a global config that a script reads. This attack is called DOM clobbering. Declare every variable with const or let inside a module, and keep settings off window. Clean user HTML with an allow list of tags and attributes, such as DOMPurify with SANITIZE_NAMED_PROPS. The browser's Sanitizer API, element.setHTML(), shipped in Chrome 146 and Firefox 148 but not yet in Safari, so keep a library as the fallback. Escaping every other value stays the job of Escape everything you show. Ids that your own templates write follow Keep ids unique and stable.
Examples
JavaScript example
// Unsafe: an <a id="config"> in a comment replaces this global
const unsafeEndpoint = window.config?.apiUrl;
// Safe: a module constant, and user HTML without named attributes
const config = Object.freeze({ apiUrl: '/api' });
const cleanComment = DOMPurify.sanitize(commentHtml, { SANITIZE_NAMED_PROPS: true });
Python example
import nh3
ALLOWED_ATTRIBUTES = {"a": {"href"}, "p": set(), "em": set(), "strong": set()}
def clean_comment(html: str) -> str:
return nh3.clean(html, tags=set(ALLOWED_ATTRIBUTES), attributes=ALLOWED_ATTRIBUTES)
assert "id=" not in clean_comment('<a id="config" name="config" href="/">x</a>')
How to check
A search of the scripts finds 0 reads of window.<name> or document.<name> where the name is an id on any built page. A unit test cleans <a id="config" name="config" href="/"> and the output keeps neither attribute unchanged.
Sources
Related rules
- APS-3 Escape everything you show in Application security
- CSS-22 Keep ids unique and stable in HTML and CSS
- CSS-24 Clone markup that scripts add from a template element in HTML and CSS
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/html-css/html-structure-and-reuse/no-named-element-globals">Agent Wranglers HTML and CSS playbook</a>. In code you write, add a comment next to it with the same link.