browser-security/no-postmessage-innerhtml
The rule provides **LLM-optimized error messages** (Compact 2-line format) with actionable security guidance:
🔒 Disallow using innerHTML with postMessage data
Error Message Format
The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:
⚠️ CWE-79 OWASP:A05 CVSS:6.1 | Cross-site Scripting (XSS) detected | MEDIUM [SOC2,PCI-DSS,GDPR,ISO27001]
Fix: Review and apply the recommended fix | https://owasp.org/Top10/A05_2021/Message Components
| Component | Purpose | Example |
|---|---|---|
| Risk Standards | Security benchmarks | CWE-79 OWASP:A05 CVSS:6.1 |
| Issue Description | Specific vulnerability | Cross-site Scripting (XSS) detected |
| Severity & Compliance | Impact assessment | MEDIUM [SOC2,PCI-DSS,GDPR,ISO27001] |
| Fix Instruction | Actionable remediation | Follow the remediation steps below |
| Technical Truth | Official reference | OWASP Top 10 |
Rule Details
This rule prevents using innerHTML, outerHTML, insertAdjacentHTML(), or document.write() with data received from postMessage events. This pattern enables XSS attacks through malicious messages.
Why is this dangerous?
When you use innerHTML with postMessage data:
- Any window can send messages to your page
- Malicious HTML/scripts are executed when assigned to innerHTML
- Attackers can steal data, session tokens, and perform actions as the user
Examples
❌ Incorrect
// Direct innerHTML with event.data
window.addEventListener('message', (event) => {
element.innerHTML = event.data;
});
// Nested property access
window.addEventListener('message', (event) => {
container.innerHTML = event.data.content;
});
// outerHTML is equally dangerous
window.addEventListener('message', (event) => {
widget.outerHTML = event.data.html;
});
// insertAdjacentHTML
window.addEventListener('message', (event) => {
list.insertAdjacentHTML('beforeend', event.data);
});
// document.write (rare but dangerous)
window.addEventListener('message', (event) => {
document.write(event.data);
});✅ Correct
// Use textContent for plain text
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted.com') return;
element.textContent = event.data;
});
// Sanitize before using innerHTML
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted.com') return;
const sanitized = DOMPurify.sanitize(event.data);
element.innerHTML = sanitized;
});
// Use intermediate variable (sanitized)
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted.com') return;
const safeHtml = DOMPurify.sanitize(event.data.content);
container.innerHTML = safeHtml;
});
// Use DOM APIs instead
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted.com') return;
const text = document.createTextNode(event.data);
element.appendChild(text);
});Options
{
"browser-security/no-postmessage-innerhtml": [
"error",
{
"allowInTests": true
}
]
}| Option | Type | Default | Description |
|---|---|---|---|
allowInTests | boolean | true | Skip checking in test files (_.test.ts, _.spec.ts) |
When Not To Use It
You may disable this rule if:
- You're handling postMessage in a sandbox/isolated context
- You have thorough sanitization that the rule can't detect
However, always sanitize postMessage data before rendering as HTML.
Related Rules
browser-security/require-postmessage-origin-check- Require origin validationbrowser-security/no-postmessage-wildcard-origin- Prevent wildcard targetOriginbrowser-security/no-innerhtml- General innerHTML prevention
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Event Data Stored in Variable
Why: Data stored in variables not traced.
// ❌ NOT DETECTED - Data stored first
window.addEventListener('message', (event) => {
const html = event.data;
element.innerHTML = html;
});Mitigation: Sanitize before any variable assignment.
Separate Handler Function
Why: Handler internals not analyzed.
// ❌ NOT DETECTED - External handler
window.addEventListener('message', handlePostMessage);Mitigation: Apply rule to handler implementations.
Custom Sanitizer
Why: Non-standard sanitizers may not be recognized.
// ❌ NOT DETECTED - Custom sanitizer
element.innerHTML = mySanitizeFunc(event.data);Mitigation: Configure trusted sanitizer names.
OWASP Mapping
| Category | ID |
|---|---|
| OWASP Top 10 2021 | A03:2021 - Injection |
| CWE | CWE-79 |
| CVSS | 8.8 (High) |
browser-security/no-jwt-in-storage
This rule prevents storing JWT tokens in browser storage (localStorage/sessionStorage). JWTs stored in these locations are fully accessible to JavaScript, makin
browser-security/no-postmessage-wildcard-origin
This rule prevents using `"*"` as the `targetOrigin` parameter in `postMessage()` calls. Using a wildcard allows **any window** to receive the message, potentia