no-disabled-template-escaping
Disallows assigning `false` to `escapeMarkup`, which disables template HTML auto-escaping (CWE-79)
CWE: CWE-79 OWASP: A03:2021 — Injection
Auto-escaping is the XSS defence of a template engine, and escapeMarkup = false turns it
off for every template at once. This rule is part of
eslint-plugin-secure-coding,
and is the drop-in for eslint-plugin-security's detect-disable-mustache-escape.
Quick Summary
| Aspect | Details |
|---|---|
| CWE Reference | CWE-79 (Cross-site Scripting) |
| Severity | Medium (CVSS 6.1) |
| Auto-Fix | ❌ No — whether a template needs raw HTML is a design decision, not a rewrite |
| Category | Security |
Vulnerability and Risk
Vulnerability: With escapeMarkup on, a template engine turns <script> in a value
into the text <script>. With it false, every interpolated value is written into
the page as HTML.
Risk: One user-controlled value in any template rendered by that engine becomes stored or reflected cross-site scripting. The setting is made once, usually in setup code, so no review of an individual template ever sees it.
Rule Details
Reports an assignment of the literal false to a property named escapeMarkup, in any
spelling of the property:
view.escapeMarkup = falseview['escapeMarkup'] = falseview[`escapeMarkup`] = false
It does not report:
- a bare variable named
escapeMarkup— it is not an option on anything; escapeMarkup = true, or any value other than the literalfalse(the string'false'is truthy);view[escapeMarkup] = falsewhereescapeMarkupis a variable — which property that writes is decided at runtime;- a comparison such as
view.escapeMarkup === false.
Examples
❌ Incorrect
a.escapeMarkup = false;
view['escapeMarkup'] = false;
this.options.escapeMarkup = false;✅ Correct
// Leave auto-escaping on.
view.escapeMarkup = true;
// Render the one trusted, sanitized fragment through the engine's raw-output
// syntax (for example a triple mustache) instead of disabling escaping globally.Options
This rule has no options.
Error Message Format
🔒 CWE-79 OWASP:A05-Injection CVSS:6.1 | escapeMarkup is set to false, so the template engine renders every interpolated value as raw HTML. One user-controlled value in any template is then a cross-site scripting vulnerability. | MEDIUM [SOC2,PCI-DSS,GDPR,ISO27001]
Fix: Remove the assignment and keep auto-escaping on. Render trusted HTML through the template engine's explicit raw-output syntax at the one site that needs it, after sanitizing it. | https://cwe.mitre.org/data/definitions/79.htmlKnown False Negatives
The option set in an object literal
Why: The rule reports the assignment form x.escapeMarkup = false, as
eslint-plugin-security does. new Engine({ escapeMarkup: false }) is not an assignment.
Mitigation: Keep engine configuration in one reviewed module.
A falsy value other than false
Why: x.escapeMarkup = 0, = null or = !1 disables escaping in an engine that
tests the option for truthiness, but whether a given engine does is not visible in the
AST.
Mitigation: Write the option as a boolean.
The key held in a variable
Why: const k = 'escapeMarkup'; x[k] = false names the property only at runtime.
Mitigation: Accepted; the rule does not do data-flow.
Further Reading
- CWE-79 — Improper Neutralization of Input During Web Page Generation
- OWASP XSS Prevention Cheat Sheet
Related Rules
no-template-injection— user input used as the template itself
Use this rule
npm install -D oxlint-plugin-secure-coding{ "jsPlugins": ["oxlint-plugin-secure-coding"], "rules": { "secure-coding/no-disabled-template-escaping": "error" }}import { defineConfig } from 'vite-plus';export default defineConfig({ lint: { jsPlugins: ['oxlint-plugin-secure-coding'], rules: { 'secure-coding/no-disabled-template-escaping': 'error', }, },});oxlint-plugin-secure-coding re-exports eslint-plugin-secure-coding/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.
Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.