38 KiB
Frontend JavaScript/TypeScript Web Security Spec (Vanilla Browser JS/TS, Modern Browsers)
This document is designed as a security spec that supports:
- Secure-by-default code generation for new frontend JavaScript/TypeScript (no specific framework assumed).
- Security review / vulnerability hunting in existing frontend code (passive “notice issues while working” and active “scan the repo and report findings”).
It is intentionally written as a set of normative requirements (“MUST/SHOULD/MAY”) plus audit rules (what bad patterns look like, how to detect them, and how to fix/mitigate them).
0) Safety, boundaries, and anti-abuse constraints (MUST FOLLOW)
-
MUST NOT request, output, log, hard-code, or commit secrets (API keys intended to be secret, private keys, passwords, OAuth refresh tokens, session tokens, cookies). Notes:
- Frontend code is inherently observable by end users. If a value must remain secret, it must not be in browser-delivered code.
- If the project uses “public” keys (e.g., publishable analytics keys), they MUST be treated as non-secret and scoped accordingly.
-
MUST NOT “fix” security by disabling protections (e.g., weakening CSP with
unsafe-inline/unsafe-evalwithout justification, removing origin checks forpostMessage, switching toinnerHTMLfor convenience, accepting arbitrary redirects/URLs, or turning off sanitization). -
MUST provide evidence-based findings during audits: cite file paths, code snippets, and relevant HTML/CSP/config values that justify the claim.
-
MUST treat uncertainty honestly:
- Security headers (CSP, frame-ancestors, etc.) might be set by server/edge/CDN rather than in repo code. If not visible, report as “not visible here; verify at runtime/edge config.” (Also note that
<meta http-equiv=...>only simulates a subset of headers; don’t assume other security headers exist just because a meta tag exists.) (MDN Web Docs)
- Security headers (CSP, frame-ancestors, etc.) might be set by server/edge/CDN rather than in repo code. If not visible, report as “not visible here; verify at runtime/edge config.” (Also note that
1) Operating modes
1.1 Generation mode (default)
When asked to write new frontend JS/TS code or modify existing code:
- MUST follow every MUST requirement in this spec.
- SHOULD follow every SHOULD requirement unless the user explicitly says otherwise.
- MUST prefer safe-by-default browser APIs and proven libraries over custom security code (especially for HTML sanitization).
- MUST avoid introducing new risky sinks (DOM XSS injection sinks like
innerHTML, navigation tojavascript:URLs, dynamic code execution viaeval/Function, unsafepostMessage, unsafe third-party script loading, etc.). (OWASP Cheat Sheet Series)
1.2 Passive review mode (always on while editing)
While working anywhere in a frontend repo (even if the user did not ask for a security scan):
- MUST “notice” violations of this spec in touched/nearby code.
- SHOULD mention issues as they come up, with a brief explanation + safe fix.
1.3 Active audit mode (explicit scan request)
When the user asks to “scan”, “audit”, or “hunt for vulns”:
- MUST systematically search the codebase for violations of this spec.
- MUST output findings in a structured format (see §2.3).
Recommended audit order:
- HTML entrypoints (
index.html, server-rendered templates), script/style includes, and any CSP delivery (header vs meta). (W3C) - DOM XSS sinks (
innerHTML,document.write,insertAdjacentHTML, event-handler attributes) and their data sources (URL params/hash, storage, postMessage, API responses). (OWASP Cheat Sheet Series) - Navigation/redirect handling (
window.location*, link targets, URL allowlists) includingjavascript:URL hazards. (MDN Web Docs) - Cross-origin communication (
postMessage, iframe embed patterns, sandboxing). (MDN Web Docs) - Storage of sensitive data (localStorage/sessionStorage) and assumptions about trust. (OWASP Cheat Sheet Series)
- Third-party scripts / tag managers / CDNs, and integrity controls (SRI) and policy controls (CSP). (OWASP Cheat Sheet Series)
- DOM clobbering gadgets and unsafe reliance on
window/documentnamed properties. (OWASP Cheat Sheet Series)
2) Definitions and review guidance
2.1 Untrusted input (treat as attacker-controlled unless proven otherwise)
Examples include:
- URL-derived data:
location.href,location.search,location.hash,document.baseURI,new URLSearchParams(location.search), routing fragments. (OWASP Cheat Sheet Series) - DOM content that may include user-controlled markup (comments, profiles, CMS content, markdown-to-HTML output, etc.), especially if inserted dynamically. (OWASP Cheat Sheet Series)
postMessageevent data (event.data) and metadata (event.origin) from other windows/frames. (MDN Web Docs)- Browser storage:
localStorage,sessionStorage, IndexedDB (contents can be attacker-influenced via XSS or local machine access; never treat as “trusted”). (OWASP Cheat Sheet Series) - Any data returned from network calls (even if from “your API”), because it may contain stored attacker content that becomes dangerous only when inserted into the DOM. (OWASP Cheat Sheet Series)
2.2 Dangerous sink (DOM XSS / code execution sink)
A sink is any API/operation that can execute script or interpret attacker-controlled strings as HTML/JS/URL in a security-sensitive way. High-signal sinks include:
- HTML parsing / insertion:
innerHTML,outerHTML,insertAdjacentHTML,document.write,document.writeln. (OWASP Cheat Sheet Series) - Dynamic code execution:
eval,new Function,setTimeout("..."),setInterval("..."). (MDN Web Docs) - Navigation to script-bearing URLs (e.g.,
javascript:) via setters likeLocation.href/window.location(and via linkhrefif attacker-controlled). (MDN Web Docs) - Setting event handler attributes from strings, e.g.
setAttribute("onclick", "..."). (OWASP Cheat Sheet Series)
2.3 Required audit finding format
For each issue found, output:
- Rule ID:
- Severity: Critical / High / Medium / Low
- Location: file path + function/class/module + line(s)
- Evidence: the exact code/config snippet
- Impact: what could go wrong, who can exploit it
- Fix: safe change (prefer minimal diff)
- Mitigation: defense-in-depth if immediate fix is hard
- False positive notes: what to verify if uncertain
3) Secure baseline: minimum production configuration (MUST in production)
This is the smallest baseline that prevents common frontend JS/TS security misconfigurations. Some items are “in repo” (HTML/JS) and some may live at the server/edge.
3.1 Content Security Policy (CSP) baseline (SHOULD; MUST for high-risk apps)
-
SHOULD deliver CSP via HTTP response headers when possible.
-
MAY deliver CSP via an HTML
<meta http-equiv="Content-Security-Policy" ...>tag when you cannot set headers (e.g., purely static hosting constraints). (MDN Web Docs) -
If using CSP via
<meta http-equiv>, MUST understand the limitations:- The policy only applies to content that follows the meta element (so it must appear very early, before any scripts/resources you want governed). (W3C)
- The following directives are not supported in a meta-delivered policy and will be ignored:
report-uri,frame-ancestors, andsandbox. (W3C) - “Report-only” CSP cannot be set via a meta element. (W3C)
Practical baseline goals:
- Avoid script sources
unsafe-inlineandunsafe-eval(they significantly weaken CSP’s value against XSS). (MDN Web Docs) - Prefer nonce- or hash-based script policies if you need inline scripts. (MDN Web Docs)
- Consider enabling Trusted Types enforcement where feasible. (MDN Web Docs)
3.2 Third-party scripts baseline (SHOULD)
- SHOULD minimize third-party script execution and treat it as equivalent privilege to first-party JS (it runs with your origin’s privileges). (OWASP Cheat Sheet Series)
- SHOULD use Subresource Integrity (SRI) for third-party scripts/styles loaded from CDNs. (MDN Web Docs)
3.3 Cross-window communication baseline (SHOULD)
- SHOULD restrict
postMessagecommunications to explicit origins, and validate both origin and message shape. (MDN Web Docs)
4) Rules (generation + audit)
Each rule contains: required practice, insecure patterns, detection hints, and remediation.
JS-XSS-001: Do not inject untrusted HTML into the DOM (avoid innerHTML and friends)
Severity: Critical if you can prove attacker-controlled input can reach these APIs; otherwise Medium
Required:
-
MUST treat
innerHTML,outerHTML, andinsertAdjacentHTMLas dangerous sinks when their input can contain untrusted data. (OWASP Cheat Sheet Series) -
MUST prefer safe DOM APIs that do not parse HTML:
textContentfor text. (OWASP Cheat Sheet Series)document.createElement,appendChild,setAttributefor non-event-handler attributes. (OWASP Cheat Sheet Series)
-
If HTML insertion is truly required, SHOULD sanitize with a well-reviewed HTML sanitizer and strongly consider enforcing Trusted Types to confine usage to audited code paths. (MDN Web Docs)
Insecure patterns:
el.innerHTML = userInputel.insertAdjacentHTML('beforeend', userInput)el.outerHTML = userInput
Detection hints:
- Search for:
.innerHTML,.outerHTML,insertAdjacentHTML(. - Trace the origin of inserted string: URL params/hash, postMessage, storage, API responses, DOM attributes. (OWASP Cheat Sheet Series)
Fix:
-
Replace with
textContentfor plain text. (OWASP Cheat Sheet Series) -
For structured UI, build DOM nodes explicitly.
-
For “rich text” requirements:
- Sanitize using an allowlist-based sanitizer.
- Prefer returning safe “components” instead of arbitrary HTML strings.
- Use Trusted Types enforcement to ensure only
TrustedHTMLreaches sinks where supported. (MDN Web Docs)
Mitigation:
- Deploy a strict CSP and consider Trusted Types enforcement (
require-trusted-types-for 'script'). (MDN Web Docs)
False positive notes:
- If the string is provably constant or fully generated from trusted constants, it may be safe. Still prefer safer APIs.
JS-XSS-002: Avoid document.write / document.writeln (XSS + document clobbering hazards)
Severity: Critical if you can prove attacker-controlled input can reach these APIs; otherwise Medium
Required:
- MUST avoid
document.write()anddocument.writeln()in production code (they are XSS vectors and can be abused with crafted HTML even if some browsers block injected<script>in certain situations). (MDN Web Docs) - If legacy use is unavoidable, MUST ensure no untrusted input reaches these APIs and SHOULD enforce Trusted Types (
TrustedHTML) where supported. (MDN Web Docs)
Insecure patterns:
document.write(userInput)document.writeln(getParam('q'))
Detection hints:
- Search for
document.write(,document.writeln(. (OWASP Cheat Sheet Series)
Fix:
- Replace with DOM manipulation (
createElement,appendChild) or safe text insertion (textContent). (OWASP Cheat Sheet Series)
Mitigation:
- Strict CSP + Trusted Types enforcement reduces blast radius if a sink remains. (MDN Web Docs)
JS-XSS-003: Do not use string-to-code execution (eval, new Function, string timeouts)
Severity: Critical if you can prove attacker-controlled input can reach these APIs; otherwise Medium
Required:
-
MUST NOT pass untrusted data to:
eval()new Function(...)setTimeout("...")/setInterval("...")with string arguments (MDN Web Docs)
-
SHOULD avoid these APIs entirely in modern frontend code; refactor to non-eval logic. (MDN Web Docs)
-
MUST NOT “fix CSP breakage” by adding
unsafe-evalunless there is a documented, reviewed justification and compensating controls. (MDN Web Docs)
Insecure patterns:
eval(userInput)new Function("return " + userInput)()setTimeout(userInput, 0)where userInput is a string
Detection hints:
- Search for
eval(,new Function,setTimeout(",setInterval(". - Also search for construction of code strings used later.
Fix:
-
Replace dynamic code with:
- structured data + explicit branching/handlers,
- JSON parsing (
JSON.parse) instead ofevalfor JSON. (OWASP Cheat Sheet Series)
Mitigation:
- CSP that blocks
eval()-like APIs by default, and avoidunsafe-eval. (MDN Web Docs) - Consider Trusted Types for controlled cases, but treat it as a hardening layer, not a license to keep eval patterns. (MDN Web Docs)
JS-XSS-004: Do not set event handler attributes from strings (e.g., setAttribute("onclick", "..."))
Severity: High
Required:
- MUST NOT use
setAttribute("on…", string)or similar patterns with untrusted data; this coerces strings into executable code in the event-handler context. (OWASP Cheat Sheet Series) - SHOULD prefer
addEventListenerwith function references.
Insecure patterns:
el.setAttribute("onclick", userInput)el.onclick = userControlledString(string assignment)
Detection hints:
- Search for
.setAttribute("on,.onclick =,.onmouseover =, etc. - Trace whether RHS can be influenced by URL/hash/storage/postMessage. (OWASP Cheat Sheet Series)
Fix:
- Replace with
addEventListener("click", () => { ... }). - If dynamic dispatch is needed, use an allowlisted mapping from identifiers to functions (no string eval). (OWASP Cheat Sheet Series)
JS-URL-001: Sanitize and allowlist URLs before navigation (especially window.location / location.replace)
Severity: Low (High if you can prove an attacker can fully control the URL)
IMPORTANT: This can cause a lot of false positives. Please perform extra analysis to determine if the url is fully attacker controlled. If not fully attacker controlled, then this is informational at best.
NOTE: It may be important functionality to be able to redirect to any given url. If that is the goal of the feature, then at a minimum, ensure it checks the schema even if the origin is allowed to be anything.
Required:
-
MUST treat any assignment to navigation targets as security-sensitive:
window.location = ...location.href = ...location.assign(...)location.replace(...)(MDN Web Docs)
-
MUST prevent navigation to
javascript:URLs (and generally other script-bearing/active schemes), especially when input is derived from URL params, storage, or messages. (MDN Web Docs). Only allowhttp:andhttps:. -
SHOULD validate/allowlist the destination. A safe baseline is:
- Allow only same-origin relative paths, OR
- Allow only a strict allowlist of origins and protocols (typically
https:and optionallyhttp:for localhost dev). (OWASP Cheat Sheet Series)
Insecure patterns:
location.replace(getParam("next"))window.location = userSuppliedUrllocation.assign(window.redirectTo || "/")whereredirectTocan be clobbered or attacker-set (OWASP Cheat Sheet Series)
Detection hints:
- Search for
window.location,location.href,location.assign,location.replace. - Search for common redirect parameters:
next,returnTo,redirect,url,continue. - Search for
javascript:literal usage. (MDN Web Docs)
Fix:
-
Parse and validate with
new URL(value, location.origin)and then enforce:url.protocolin{ "https:" }(and only includehttp:in explicit dev-only code paths),url.originequalslocation.originfor internal redirects, or in a strict allowlist for external redirects,- optionally allow only specific path prefixes. (MDN Web Docs)
-
If validation fails, navigate to a safe default (home/dashboard).
Mitigation:
- Deploy strict CSP and Trusted Types enforcement to reduce the impact of DOM XSS sinks, but note that Trusted Types do not prevent every possible unsafe navigation scenario on their own. (W3C)
False positive notes:
IMPORTANT: This can cause a lot of false positives. Please perform extra analysis to determine if the url is fully attacker controlled. If not fully attacker controlled, then this is informational at best.
- Some apps intentionally support external redirects (SSO, payment flows). Those MUST be allowlisted and documented.
JS-URL-002: Sanitize URLs before inserting into DOM URL contexts (href, src, etc.)
Severity: Low (High if you can prove an attacker can fully control the URL)
IMPORTANT: This can cause a lot of false positives. Please perform extra analysis to determine if the url is fully attacker controlled. If not fully attacker controlled, then this is informational at best.
Required:
-
MUST treat setting URL-bearing DOM attributes/properties as security-sensitive, especially:
a.href,img.src,script.src,iframe.src,form.action,link.href.
-
MUST prevent script-bearing schemes (
javascript:and other active schemes) when values can be attacker-influenced. (MDN Web Docs) -
SHOULD prefer setting properties (e.g.,
a.href = url.toString()) after parsing and validation, rather than string concatenation.
Insecure patterns:
link.href = getParam("u")el.setAttribute("href", userInput)without validation- constructing URLs via concatenation with untrusted pieces
Detection hints:
- Search for
.href =,.src =,.action =,setAttribute("href",setAttribute("src". - Search for
javascript:/data:usage in URLs. (MDN Web Docs)
IMPORTANT: This can cause a lot of false positives. Please perform extra analysis to determine if the url is fully attacker controlled. If not fully attacker controlled, then this is informational at best.
Fix:
-
Use
new URL(...)and validate:- protocol allowlist
- avoid passing user-provided values into
<script src>at all (treat as code execution). (OWASP Cheat Sheet Series)
JS-CSP-001: Use CSP; meta delivery is allowed
Severity: Medium to High (depends on threat model; High when handling untrusted content)
NOTE: It is most important to set the CSP's script-src. All other directives are not as important and can generally be excluded for the ease of development.
Required:
-
SHOULD deploy a CSP as a major defense-in-depth against XSS. (MDN Web Docs)
-
MAY provide CSP via
<meta http-equiv="Content-Security-Policy" ...>when headers are not available. (MDN Web Docs) -
If CSP is delivered via meta, MUST:
- place it early (before scripts/resources you want governed), and
- not rely on unsupported directives in meta policies (
report-uri,frame-ancestors,sandbox). (W3C)
-
MUST avoid adding
unsafe-inlineas a “quick fix” for CSP issues unless explicitly required and reviewed (it defeats much of CSP’s purpose). (MDN Web Docs) -
MUST avoid adding
unsafe-evalunless explicitly required and reviewed (it allows eval-like APIs that are commonly abused). (MDN Web Docs)
Insecure patterns:
- No CSP present anywhere (repo HTML or server/edge) for an app that renders untrusted content.
- CSP includes
script-src 'unsafe-inline'and/orscript-src 'unsafe-eval'without strong justification. (MDN Web Docs) - CSP delivered via meta but includes
frame-ancestors(it will be ignored in meta). (W3C)
Detection hints:
- Search HTML for
<meta http-equiv="Content-Security-Policy". - Search server/edge configs for
Content-Security-Policyheader. - If CSP is only in meta, check it appears before any
<script>tags you want governed. (W3C)
Fix:
- Prefer header-delivered CSP at the server/edge.
- If constrained to meta, keep a strong allowlist CSP and document the limitations; implement clickjacking protections (e.g.,
frame-ancestors) at the server/edge, not in meta. (W3C)
JS-CSP-002: Prefer strict CSP (nonces/hashes); avoid inline/eval patterns in code
Severity: Medium
NOTE: It is most important to set the CSP's script-src. All other directives are not as important and can generally be excluded for the ease of development.
Required:
-
SHOULD design frontend code to work under a strict CSP:
- avoid inline scripts and inline event handlers,
- avoid eval-like APIs (see JS-XSS-003),
- allow scripts via nonce or hash when needed. (MDN Web Docs)
Insecure patterns:
- Large amounts of inline script blocks and inline
onclick="..."handlers. - Libraries that require
unsafe-eval.
Detection hints:
- Search for
<script>blocks with inline code,onclick=",onload=", etc. - Search for CSP directives containing
unsafe-inlineorunsafe-eval. (MDN Web Docs)
Fix:
- Move inline scripts into external JS files (same-origin).
- Use nonces/hashes for any unavoidable inline blocks. (MDN Web Docs)
JS-TT-001: Use Trusted Types to reduce DOM XSS attack surface (where supported)
Severity: Low
Required:
- SHOULD consider enabling Trusted Types enforcement with CSP
require-trusted-types-for 'script'to make many DOM XSS sinks reject raw strings. (MDN Web Docs) - If using Trusted Types, SHOULD also use the CSP
trusted-typesdirective to restrict which policies can be created (reduces policy sprawl and improves auditability). (MDN Web Docs) - MUST keep Trusted Types policy code small, heavily reviewed, and used as the only path to produce trusted values for sinks. (W3C)
Insecure patterns:
- “Trusted Types enabled” but policy simply returns input unchanged (no sanitization/validation).
- Many ad-hoc policies created across the codebase without restriction.
- Belief that Trusted Types alone prevents all unsafe navigations or all XSS classes. (It targets DOM injection sinks; it is not a universal sandbox.) (W3C)
Detection hints:
- Search for CSP directives:
require-trusted-types-forandtrusted-types. - Search code for
trustedTypes.createPolicy(and inspect policy implementations. (MDN Web Docs)
Fix:
- Add a small set of well-reviewed policies (e.g.,
createHTMLthat sanitizes). - Restrict allowed policies via
trusted-types <policyName...>. - Migrate sinks to require
TrustedHTML/TrustedScriptURLas appropriate. (MDN Web Docs)
JS-MSG-001: postMessage must use strict origin validation and explicit targetOrigin
Severity: Medium (High if dangerous behavior can be triggered via postMessage)
Required:
-
When sending messages, MUST set an explicit
targetOrigin(not*) to avoid sending data to an unexpected origin after redirects or window origin changes. (MDN Web Docs) -
When receiving messages, MUST:
- Validate
event.originexactly against an allowlist of expected origins (no substring matching). (OWASP Cheat Sheet Series) - Consider validating
event.source(expected window reference) when applicable. (MDN Web Docs) - Validate
event.datastructure (schema/shape) and treat it purely as data (never evaluate it as code and never insert into DOM withinnerHTML). (OWASP Cheat Sheet Series)
- Validate
Insecure patterns:
otherWindow.postMessage(payload, "*")window.addEventListener("message", (e) => { doSomething(e.data) })with noorigincheckif (e.origin.includes("trusted.com"))(substring checks)el.innerHTML = e.data(OWASP Cheat Sheet Series)
Detection hints:
- Search for
postMessage(,addEventListener("message",onmessage =. - Audit all handlers for explicit allowlist checks on
event.origin. (OWASP Cheat Sheet Series)
Fix:
-
Define an allowlist:
const ALLOWED = new Set(["https://app.example.com", "https://accounts.example.com"]);NOTE: For ease of development, you can use the current page's originwindow.location.originas a safe default origin.
-
On receive:
if (!ALLOWED.has(event.origin)) return;- Validate
event.datawith a strict schema and reject unknown/extra fields.
-
On send:
- use the exact expected origin string as
targetOrigin. (OWASP Cheat Sheet Series)
- use the exact expected origin string as
Mitigation:
- Combine with a strict CSP and avoid DOM sinks in message paths. (MDN Web Docs)
JS-STORAGE-001: Web Storage is not a safe place for secrets (and is attacker-influencable)
Severity: Low
Required:
- MUST NOT store sensitive secrets or session identifiers in
localStorage(orsessionStorage) if compromise would matter; a single XSS can exfiltrate everything in storage. (OWASP Cheat Sheet Series) - MUST treat values read from storage as untrusted input (attackers can load malicious values into storage via XSS). (OWASP Cheat Sheet Series)
- SHOULD prefer server-set cookies with
HttpOnlyfor session identifiers (JS cannot setHttpOnly, so avoid storing session IDs in JS-accessible storage). (OWASP Cheat Sheet Series) - SHOULD avoid hosting multiple unrelated apps on the same origin if they rely on storage separation (storage is origin-wide). (OWASP Cheat Sheet Series)
Insecure patterns:
localStorage.setItem("access_token", token)localStorage.setItem("session", sessionId)- Assuming
localStorageis “trusted because same-origin.”
Detection hints:
- Search for
localStorage.getItem,localStorage.setItem,sessionStorage.*. - Flag storage keys named
token,jwt,session,auth,refresh. (OWASP Cheat Sheet Series)
Fix:
- Use server-managed sessions or short-lived tokens delivered and rotated securely, with careful XSS defenses (CSP/Trusted Types) and minimal JS exposure.
- If storage must be used for non-sensitive state, keep it non-auth and validate/escape before use.
JS-SUPPLY-001: Third-party JavaScript is a major supply-chain risk; minimize and control it
Severity: Low
Required:
-
MUST treat third-party JS as equivalent to first-party JS in privilege (it can execute arbitrary code in your origin and access DOM data). (OWASP Cheat Sheet Series)
-
SHOULD minimize third-party scripts and prefer:
- self-hosting / script mirroring,
- strict CSP allowlists,
- SRI for any CDN-hosted scripts,
- ongoing monitoring for unexpected changes. (OWASP Cheat Sheet Series)
Insecure patterns:
- Loading arbitrary remote scripts from many vendors without review.
- Using tag managers that can dynamically inject scripts with no integrity controls.
- Allowing scripts from broad wildcards in CSP (e.g.,
script-src *). (MDN Web Docs)
Detection hints:
- Search HTML for
<script src="https://...">andtag managersnippets. - Search CSP
script-srcsources for wildcards or overly broad domains. - Search for dynamic script injection:
document.createElement("script"),script.src = ...,appendChild(script). (OWASP Cheat Sheet Series)
Fix:
- Remove unnecessary third-party tags.
- Self-host or mirror scripts where possible.
- Lock down CSP
script-srcto the smallest set of trusted sources. - Add SRI for CDN scripts/styles. (OWASP Cheat Sheet Series)
JS-SRI-001: Use Subresource Integrity (SRI) for third-party scripts/styles
Severity: Low
Required:
- SHOULD use SRI to ensure browsers only load third-party resources if they match an expected cryptographic hash. (MDN Web Docs)
- MUST update SRI hashes whenever the underlying resource changes (pin versions; avoid “latest” URLs).
Insecure patterns:
<script src="https://cdn.example.com/lib.js"></script>with nointegrity.- Loading
latestor unpinned third-party resources.
Detection hints:
- Search for
<script src="https://and<link rel="stylesheet" href="https://withoutintegrity=. - Check whether
integrityis present and uses strong hashes (sha256/384/512 are typical). (MDN Web Docs)
Fix:
- Add
integrity="sha384-..."(or appropriate) and ensure proper CORS mode where needed. - Prefer self-hosting critical libraries.
FS-DOMC-001: Prevent DOM clobbering (avoid relying on window/document named properties)
Severity: Medium to High (can become Critical if it enables script loading or javascript: navigation)
Required:
- MUST NOT rely on implicit global variables or
window.someName/document.someNamelookups that can be clobbered by injected HTML elements with matchingid/name. (OWASP Cheat Sheet Series) - MUST avoid patterns like
let x = window.redirectTo || "/safe"; location.assign(x);whereredirectTocould be clobbered to an<a>element whosehrefis attacker-controlled (includingjavascript:). (OWASP Cheat Sheet Series) - SHOULD use explicit variable declarations, local scope, and explicit DOM queries (
getElementById) rather than named property access. (OWASP Cheat Sheet Series) - If the app inserts user-controlled markup (even sanitized), SHOULD ensure sanitization strategies consider
id/namecollisions. (OWASP Cheat Sheet Series)
Insecure patterns:
const cfg = window.config || {};used for security-sensitive URLs.const redirect = window.redirectTo || "/"; location.assign(redirect);(OWASP Cheat Sheet Series)- Loading scripts from
window.*config values without strict validation.
Detection hints:
- Search for
window.anddocument.used as config stores (especially||fallback patterns). - Search for usage of
location.assign/replacewith variables that come fromwindow/documentproperties. - Search for dynamic script creation (
createElement('script')) where.srccomes from a non-local variable. (OWASP Cheat Sheet Series)
Fix:
- Store config in module-scoped constants (not on
window/document) and pass it explicitly. - Validate any URL-like config with protocol/origin allowlists (see FEJS-URL-001). (OWASP Cheat Sheet Series)
- Consider hardening: sanitization, CSP, and (in limited cases) freezing sensitive objects, but treat these as defense-in-depth, not a substitute for safe coding patterns. (OWASP Cheat Sheet Series)
5) Practical scanning heuristics (how to “hunt”)
When actively scanning, use these high-signal patterns:
-
DOM XSS sinks:
.innerHTML,.outerHTML,insertAdjacentHTML(document.write(,document.writeln((OWASP Cheat Sheet Series)
-
Dangerous navigation / URL sinks:
window.location,location.href,location.assign,location.replacejavascript:literals (and other suspicious schemes likedata:text/html) (MDN Web Docs)
-
String-to-code execution:
eval(,new Function,setTimeout(",setInterval("(MDN Web Docs)
-
Event-handler string injection:
.setAttribute("on,.onclick =,.onload =with strings (OWASP Cheat Sheet Series)
-
postMessage:postMessage(with"*"as targetOriginaddEventListener("message"without strictevent.originallowlist checks (MDN Web Docs)
-
Storage:
localStorage.setItem(/getItem(,sessionStorage.*- keys containing
token,jwt,session,auth,refresh(OWASP Cheat Sheet Series)
-
CSP and related:
Content-Security-Policyheader config (server/edge)<meta http-equiv="Content-Security-Policy" ...>- CSP containing
unsafe-inlineorunsafe-eval require-trusted-types-for/trusted-typesdirectives (MDN Web Docs)
-
Third-party scripts:
<script src="https://...">withoutintegrity=- Tag manager snippets and dynamic script injection code paths (MDN Web Docs)
-
DOM clobbering gadgets:
window.<name> || ...anddocument.<name> || ...patterns- security-sensitive usage of
window/documentproperties as config sources (OWASP Cheat Sheet Series)
Always try to confirm:
- data origin (untrusted vs trusted),
- sink type (HTML parse, navigation, code execution, message handling, storage),
- protective controls present (CSP, Trusted Types, sanitizers, strict allowlists, schema validation).
6) Sources (accessed 2026-01-27)
Primary standards / platform docs:
- W3C Content Security Policy Level 2 (HTML
<meta>delivery restrictions; unsupported directives in meta CSP):https://www.w3.org/TR/CSP2/(W3C) - MDN: CSP Guide (strict CSP, nonces/hashes,
unsafe-inline/unsafe-eval, eval blocking):https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP(MDN Web Docs) - MDN:
<meta http-equiv>(CSP via meta and warning about meta-based security headers):https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/http-equiv(MDN Web Docs) - MDN:
frame-ancestors(and note it’s not supported in<meta>):https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-ancestors(MDN Web Docs)
DOM XSS and dangerous sinks:
- OWASP: DOM Based XSS Prevention Cheat Sheet (dangerous sinks + safe patterns like
textContent):https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html(OWASP Cheat Sheet Series) - MDN:
innerHTML(security considerations):https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML(MDN Web Docs) - MDN:
insertAdjacentHTML(security considerations):https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML(MDN Web Docs) - MDN:
document.write()/document.writeln()(security considerations):https://developer.mozilla.org/en-US/docs/Web/API/Document/writeandhttps://developer.mozilla.org/en-US/docs/Web/API/Document/writeln(MDN Web Docs)
URL scheme hazards:
- MDN:
javascript:URLs (execution on navigation; discouraged; referenceswindow.location):https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/javascript(MDN Web Docs)
Trusted Types:
- W3C: Trusted Types spec (DOM XSS sinks include
Element.innerHTMLandLocation.hrefsetters; goals and limitations):https://www.w3.org/TR/trusted-types/(W3C) - MDN:
require-trusted-types-fordirective:https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/require-trusted-types-for(MDN Web Docs) - MDN:
trusted-typesdirective:https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/trusted-types(MDN Web Docs)
Cross-window messaging:
- MDN:
window.postMessage(security guidance: specify targetOrigin; validate origin):https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage(MDN Web Docs) - OWASP: HTML5 Security Cheat Sheet (Web Messaging guidance: explicit origin, strict checks, no
innerHTML):https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html(OWASP Cheat Sheet Series)
Third-party scripts and integrity:
- OWASP: Third Party JavaScript Management Cheat Sheet (risks and mitigations including SRI/mirroring):
https://cheatsheetseries.owasp.org/cheatsheets/Third_Party_Javascript_Management_Cheat_Sheet.html(OWASP Cheat Sheet Series) - MDN: Subresource Integrity overview:
https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Subresource_Integrity(MDN Web Docs) - W3C: Subresource Integrity spec:
https://www.w3.org/TR/sri-2/(W3C)
DOM clobbering:
- OWASP: DOM Clobbering Prevention Cheat Sheet (named property access risk; example attacks involving
location.assignandjavascript:):https://cheatsheetseries.owasp.org/cheatsheets/DOM_Clobbering_Prevention_Cheat_Sheet.html(OWASP Cheat Sheet Series)