Safeguard
Security Guides•

Does Vue's v-html make your app unsafe? When it is acceptable

v-html renders raw HTML and bypasses Vue's escaping. Learn when it is acceptable, when it creates XSS, and how to review every use in a Vue codebase.

Safeguard Security Team
4 min read

Not by itself, but it removes Vue's protection for that element. Vue escapes normal text and attribute bindings. v-html tells Vue to insert raw HTML, so any user-controlled string becomes a possible XSS path. Use it only for trusted or sanitized content, and review every occurrence.

What Vue escapes and what v-html skips

The Vue security guide explains that content is automatically escaped, whether you use templates or render functions. If a variable contains a script tag, the browser shows it as text. The same applies to dynamic attribute bindings. Vue does this with native browser APIs such as textContent and setAttribute, so a flaw can only exist if the browser itself is vulnerable.

The v-html directive, or the innerHTML prop in a render function, switches that off on purpose. The guide's warning is direct: user-provided HTML can never be considered 100 percent safe unless it sits in a sandboxed iframe, or in a part of the app where only the user who wrote it can ever see it.

When it is acceptable

Content sourceReasonable?Why
Static HTML your team wrote and ships in the bundleYesNo attacker influence
HTML from your CMS, edited by staffMaybeDepends on who can edit and how the CMS cleans input
Markdown rendered to HTML from usersOnly after sanitizingRendered output can still carry active markup
Comments, profiles, chat messagesAvoidDirectly attacker controlled
HTML from a third party APISanitize firstYou do not control that source

If you must render HTML that someone else can influence, run it through a maintained sanitizer before it reaches v-html, and do not modify it afterwards. A sanitizer is a second line of defense, not permission to stop thinking about the source.

How to review a Vue project

  1. Search for v-html and for innerHTML in render functions and JSX.
  2. Write down the origin of each value, from the database column or API field to the component prop.
  3. Mark each one trusted, sanitized or unknown. Fix the unknown ones first.
  4. Turn on the eslint-plugin-vue rule vue/no-v-html. It reports every use of the directive, includes an ignorePattern option for variables you have vetted, and is part of the plugin's recommended presets. The plugin's own text notes you can switch it off if you are certain the content is sanitized HTML.
  5. Check third party components too. The Vue guide recommends reviewing the source of dependencies that influence what is rendered to the DOM.

A related trap: where Vue is mounted

The Vue team says it does not treat most template XSS reports as framework vulnerabilities, because two situations cannot be protected. One is when a developer asks Vue to render unsanitized user content as a template. The other is mounting Vue on a page that already contains server-rendered, user-provided content. Attacker HTML that is harmless as plain HTML can be dangerous when Vue compiles it as a template. The guide's advice is never to mount Vue on nodes that may contain such content.

Try it yourself

Click through it at your own pace, or open it full screen. Watch how a static code scan reports a risky call with its file and line, the same shape as a v-html review list.

Safeguard offers a free scan at gold.safeguard.sh/scan that checks the dependencies in a project, including the UI libraries that render HTML for you.

Quick check

Is v-html always an XSS bug?

No. It is safe when the HTML is fully trusted. It becomes a bug when an attacker can influence the string and nothing sanitizes it.

Does a lint rule fix the problem?

It finds the uses. You still decide for each one whether the source is trusted or needs sanitizing.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.