Summary
Vue I18n: escapeParameter does not escape named values when the same call also passes a list
When escapeParameter is enabled (escapeParameterHtml in the Legacy API), Vue I18n escapes the interpolation parameters before formatting a message. escapeParams() escapes either the list values or the named values, but not both: the two branches are joined by else. When a single call passes both, for example t(key, ['...'], { named: { ... } }), the named values reach the message without being escaped.
Details
escapeParams() in packages/core-base/src/translate.ts (v11.4.13):
function escapeParams(options: TranslateOptions) {
if (isArray(options.list)) {
options.list = options.list.map(item => (isString(item) ? escapeHtml(item) : item))
} else if (isObject(options.named)) {
// ...escapes the named values
}
}
t(key, list, options) is a public overload, and TranslateOptions has a named field, so a call can carry both. The list is checked first, and the named values are then left as they are.
The translated string still goes through sanitizeTranslatedHtml() (added for CVE-2025-53892), which neutralizes event handler attributes and javascript: URLs. Other markup in the named values, such as links and forms, is inserted as is. Before the fix for GHSA-83rm-6c8r-g728, an <iframe srcdoc> in a named value also passes the sanitizer, and script runs. Versions without the sanitizer (before 9.14.5, 10.0.8 and 11.1.10, and 12.0.0-alpha.1 to alpha.3) insert the named values as HTML without any further check.
<i18n-t> is not affected: it passes either list or named values, never both, and it does not render translations as HTML.
PoC
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
legacy: false,
locale: 'en',
escapeParameter: true,
messages: {
en: { withList: '{0} {name}', withoutList: '{name}' }
}
})
const t = i18n.global.t
t('withoutList', { name: '<b>x</b>' })
// <b>x</b> escaped
t('withList', ['a'], { named: { name: '<b>x</b>' } })
// a <b>x</b> not escaped (v11.4.13)
Workarounds
- Do not pass list and named values in the same call when
escapeParameteris enabled. - Do not render translations that can contain untrusted values with
v-html. Use component interpolation (<i18n-t>) instead.
Impact
Applications are affected when they enable escapeParameter, render translations as HTML (for example with v-html), and pass untrusted named values in the same call as a list. The named values are inserted as markup: phishing links, forms, or layout changes. Together with GHSA-83rm-6c8r-g728, or on versions without the sanitizer, this leads to script execution (DOM-based XSS).
Untrusted input is rendered as active markup in a victim's browser, which can run script in their session. Typical impact: session or credential theft, and actions taken as the user.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Fixed in 11.4.14 and 12.0.0-alpha.5. escapeParams() now escapes both the list and the named values.
The fix also stops rewriting the named object that the caller passes. Before, the values of that object were replaced with their escaped form, so a second call with the same object escaped them twice.
v9 and v10 are no longer supported and will not be fixed. Please migrate to v11.
Frequently Asked Questions
- What is CVE-2026-118256? CVE-2026-118256 is a low-severity cross-site scripting (XSS) vulnerability in vue-i18n (npm), affecting versions >= 9.0.0-beta.5, < 11.4.14. It is fixed in 11.4.14, 12.0.0-alpha.5. Untrusted input is rendered as active markup in a victim's browser, which can run script in their session.
- Which packages are affected by CVE-2026-118256?
vue-i18n(npm) (versions >= 9.0.0-beta.5, < 11.4.14)@intlify/core(npm) (versions >= 9.0.0-beta.10, < 11.4.14)@intlify/core-base(npm) (versions >= 9.0.0-beta.12, < 11.4.14)petite-vue-i18n(npm) (versions >= 9.2.0-alpha.7, < 11.4.14)@intlify/vue-i18n-core(npm) (versions >= 9.2.0-alpha.7, < 11.4.14)
- Is there a fix for CVE-2026-118256? Yes. CVE-2026-118256 is fixed in 11.4.14, 12.0.0-alpha.5. Upgrade to this version or later.
- Is CVE-2026-118256 exploitable, and should I be worried? Whether CVE-2026-118256 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-118256 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-118256?
- Upgrade
vue-i18nto 11.4.14 or later - Upgrade
vue-i18nto 12.0.0-alpha.5 or later - Upgrade
@intlify/coreto 11.4.14 or later - Upgrade
@intlify/coreto 12.0.0-alpha.5 or later - Upgrade
@intlify/core-baseto 11.4.14 or later - Upgrade
@intlify/core-baseto 12.0.0-alpha.5 or later - Upgrade
petite-vue-i18nto 11.4.14 or later - Upgrade
petite-vue-i18nto 12.0.0-alpha.5 or later - Upgrade
@intlify/vue-i18n-coreto 11.4.14 or later - Upgrade
@intlify/vue-i18n-coreto 12.0.0-alpha.5 or later
- Upgrade