It can, and when it does it is code injection, not just XSS. Vue and Angular templates are executable code. If user input is concatenated into a template string, or mounted on a page that already holds user content, an attacker can run script. Keep templates fully under your control.
Templates are code, not data
In both frameworks, text you bind into a template is escaped. The template itself is different. Vue's guide calls this Rule No. 1: never use non-trusted content as your component template. Doing so is equivalent to allowing arbitrary JavaScript execution in your application, and could lead to server breaches if the code runs during server-side rendering. Vue compiles templates into JavaScript, and expressions inside them execute during rendering.
Angular states the same split: values are untrusted by default, but templates are trusted by default and should be treated as executable code. Never create templates by concatenating user input and template syntax.
How it happens by accident
| Pattern | Why it is risky |
|---|---|
| Passing a string with user data as the template option when creating a Vue app | The user text is compiled as a template |
| Mounting Vue on a page region that holds server-rendered, user-provided content | HTML that is harmless as plain HTML can be dangerous as a template |
| Generating Angular templates on the server with a server templating language | Template syntax can be injected and gives the attacker control of the app |
| Building a template to let users customize emails, dashboards or reports in the browser | Customization becomes a code execution feature |
The Vue team notes it does not usually treat reports of these as framework vulnerabilities, because there is no practical way to protect developers from them. The responsibility sits with the application.
What to do instead
- Keep templates static and in your repository. Pass user content only as data.
- Never mount Vue on nodes that may contain server-rendered, user-provided content.
- For Angular, use the default ahead-of-time (AOT) compiler in production. The guide recommends this, and the just-in-time compiler is where runtime template compilation lives.
- If you need user-defined layouts, use a restricted data format, such as a list of known block types with typed fields, and render those with your own components.
- If users truly must author code or HTML, isolate it in a sandboxed iframe on a separate origin, which the Vue guide names as the safer container.
- Add Content Security Policy and Trusted Types as extra layers. Angular's guide recommends both because they work at the DOM level.
Review questions
Ask these in code review. Does any string passed to a template option contain a variable? Does a server render user content into the same element the client app mounts on? Does any feature let a customer write expressions? One yes deserves a design change, not a patch.
Quick check
Is escaping enough to stop template injection?
No. Escaping protects values bound into a template. It does not help when the attacker's text becomes part of the template itself.
Does using Angular AOT remove the risk?
It is the recommended production setting and removes runtime template compilation, but you should still never build templates from user input.
Safeguard's free scan at gold.safeguard.sh/scan checks a project's dependencies, which helps when a template compiler or UI library has a known advisory.
Sources
Last reviewed: 19 October 2026.