📖 Scenario: You are building a simple Vue app that displays user comments on a webpage. Users can submit comments that might contain HTML or scripts. To keep the site safe, you need to prevent any harmful code from running by properly handling the comment content in the Vue template.
🎯 Goal: Build a Vue component that safely displays user comments by preventing XSS attacks using Vue's template syntax.
📋 What You'll Learn
Create a Vue component with a reactive list of comments.
Add a configuration variable to toggle raw HTML rendering.
Use Vue template syntax to safely display comments.
Add a final toggle to switch between safe text and raw HTML rendering.
💡 Why This Matters
🌍 Real World
Websites that display user-generated content must prevent harmful scripts from running. This project shows how Vue helps keep content safe by default.
💼 Career
Understanding XSS prevention is essential for frontend developers to build secure web apps and protect users from attacks.
Progress0 / 4 steps
1
Set up the comments data
Create a Vue component using <script setup> and define a reactive variable called comments as an array with these exact strings: 'Hello, world!', '<script>alert("XSS")</script>', and 'Nice to meet you!'.
Vue
Hint
Use ref from Vue to create a reactive array named comments with the exact strings.
2
Add a configuration variable to toggle raw HTML
Inside the <script setup>, add a reactive boolean variable called showRawHtml and set it to false. This will control whether comments render as plain text or raw HTML.
Vue
Hint
Use ref(false) to create showRawHtml as a reactive boolean.
3
Display comments safely using Vue template syntax
In the <template>, use a v-for loop with comment as the item to iterate over comments. Inside the loop, display each comment using double curly braces {{ comment }} to ensure safe text rendering.
Vue
Hint
Use v-for="(comment, index) in comments" and display with {{ comment }} inside a list item.
4
Add toggle to switch between safe text and raw HTML rendering
Modify the <template> so that inside the v-for loop, it conditionally renders the comment as raw HTML using v-html="comment" if showRawHtml is true, otherwise it shows safe text with {{ comment }}. Use v-if and v-else for this toggle.
Vue
Hint
Use v-if="showRawHtml" v-html="comment" and v-else with {{ comment }} inside the list item.
Practice
(1/5)
1. In Vue templates, which syntax automatically escapes content to prevent XSS attacks?
easy
A. Directly manipulating the DOM with JavaScript
B. Using v-html directive to insert HTML
C. Using triple curly braces like {{{ userInput }}}
D. Using double curly braces like {{ userInput }}
Solution
Step 1: Understand Vue's default escaping
Vue automatically escapes content inside {{ }} to prevent XSS by converting special characters to safe HTML entities.
Step 2: Compare with other methods
Using v-html inserts raw HTML and can cause XSS if content is unsafe. Direct DOM manipulation bypasses Vue's protections.
Final Answer:
Using double curly braces like {{ userInput }} -> Option D
Quick Check:
Vue escapes {{ }} content = A [OK]
Hint: Remember: {{ }} escapes content, v-html does not [OK]
Common Mistakes:
Thinking v-html escapes content automatically
Assuming v-text sanitizes HTML
Believing direct DOM manipulation is safe
2. Which of the following Vue template usages is syntactically correct and safe from XSS by default?
easy
A. <div v-html="userInput"></div>
B. <div>{{ userInput }}</div>
C. <div v-text=userInput></div>
D. <div>{{ userInput</div> }}
Solution
Step 1: Check syntax correctness
<div>{{ userInput }}</div> uses correct Vue syntax with double curly braces and quotes are properly placed.
Step 2: Check XSS safety
<div>{{ userInput }}</div> escapes content automatically, making it safe. <div v-html="userInput"></div> uses v-html which inserts raw HTML and can be unsafe. <div v-text=userInput></div> misses quotes around the binding value, causing syntax error. <div>{{ userInput</div> }} has mismatched braces causing syntax error.
Final Answer:
<div>{{ userInput }}</div> -> Option B
Quick Check:
Correct syntax + auto-escape = D [OK]
Hint: Use {{ }} with quotes for safe, correct syntax [OK]
Common Mistakes:
Using v-html without sanitizing input
Omitting quotes in directives
Mismatching curly braces
3. Given the Vue template code: <pre><template>
<div>{{ userInput }}</div>
<div v-html="userInput"></div>
</template>
And userInput is '<img src=x onerror=alert(1)>', what will be rendered in the browser?
medium
A. The first div shows the raw HTML tag as text; the second div executes the alert popup.
B. Both divs show the raw HTML tag as text without executing alert.
C. Both divs execute the alert popup.
D. The first div executes alert; the second div shows raw HTML tag as text.
Solution
Step 1: Analyze the first div with {{ userInput }}
Vue escapes the content, so the HTML tag is shown as plain text, no alert runs.
Step 2: Analyze the second div with v-html
v-html inserts raw HTML, so the <img> tag runs and triggers the alert.
Final Answer:
The first div shows the raw HTML tag as text; the second div executes the alert popup. -> Option A
Quick Check:
v-html inserts raw HTML = A [OK]
Hint: v-html runs HTML, {{ }} escapes it [OK]
Common Mistakes:
Assuming both divs escape content
Thinking v-html escapes content
Confusing which div triggers alert
4. You have this Vue template:
<div v-html="userContent"></div>
User input is not sanitized. What is the best fix to prevent XSS?
medium
A. Replace v-html with {{ userContent }} to auto-escape
B. Keep v-html but add v-text on the same element
C. Use v-html but trust all user input as safe
D. Wrap v-html inside a <script> tag
Solution
Step 1: Identify the risk of v-html with unsanitized input
v-html inserts raw HTML, so unsanitized user input can cause XSS attacks.