bhylu.com

Advertisements

Vue Security and Untrusted Content

Keep external text as text and treat templates as executable application code.

How it works

Vue escapes ordinary text interpolation. That is a useful boundary, but it does not make arbitrary HTML, URLs or templates safe. Never compile an untrusted string as a template. Validate destination schemes and permissions separately when data controls a link or an action. The fixture below displays a markup-shaped string through text interpolation so no element or handler is created.

Run the code

Use a separate empty learning folder with Node 22.12+ in the 22 series. The reviewed Node version is 22.15.1. Save all files below with their exact relative paths; downloads may keep only the basename, so create src and any tests folders as listed. This project pins Vue 3.5.44 and Vite 7.3.1. Run npm install, then npm run dev and open the local address Vite prints.

Bhylu has no Vue playground. SFCs, npm imports and routing need this local project; do not paste them into the plain HTML or JavaScript editor. Apache, MySQL and changes to Bhylu server settings are not required. The application is a fictional seed-swap learning fixture.

Example

src/App.vue

<script setup>
const note = '<img src=x onerror="window.unwanted=true">';
</script>

<template>
  <main>
    <h1>Riverside seed swap</h1>
    <p data-result>{{ note }}</p>
  </main>
</template>

Expected result

The markup-shaped note is visible text, with no image element created.

The browser review checks both the text and the absence of an injected img. This is evidence for the chosen text sink, not a universal XSS clearance. If an application intentionally supports rich text, use a maintained sanitization policy and test its allowed elements and URL rules at that separate boundary.

Check APIs and version differences in the official Vue guide.