0

this is what I have:

"de-de": "This is a description for Process\r\nHere is no line break"

I want to replace the \r\n with an <br> tag

This is what I am trying:

<p
     v-if="process.description"
     class="description"
     v-html="process.description.replace('\r\n', '<br >')"
>
</p>

This works, but if I use v-html , there are security warnings in case of XSS vulnerabilities. So v-html isn't the solution ether.

Someone an idea?

4
  • 2
    Is process.description user input? Commented Nov 9, 2022 at 14:18
  • Does this answer your question? Rendering newline character in VueJS Commented Nov 9, 2022 at 14:20
  • This is a string fetched from an api. The string is the result. Commented Nov 9, 2022 at 14:22
  • Regardless, this answer would be perfect for you. Commented Nov 9, 2022 at 14:24

3 Answers 3

2

Use Vue's built-in security

It's an interesting problem, but there is a simple solution that leverages Vue's built-in security.

If we split the description at carriage returns we can then use v-for with a template to output each text fragment appended with a <br> break.

  <p class="description" v-if="process.description">
    <template v-for="line in process.description?.split('\r\n')">
      {{line}}<br>
    </template>
  </p>

Which produces rendered output:

<p class="description">
    This is a description for Process<br>
    Here is no line break<br>
</p>

Further Reading

  1. OWASP XSS Filter Evasion Cheat Sheet
  2. Vue Security Best Practices

Snippet

For this test, a XSS alert has been embedded in the description. Vue escapes the alert and displays it as text. Yet, if we were to use v-html to render the description it would trigger the XSS alert.

const {
  createApp
} = Vue

createApp({
  data() {
    return {
      process: {
        description: 'This is a description for Process\r\nHere is no line break\r\n<svg/onload=alert("XSS")>'
      }
    }
  }
}).mount('#app')
body {
  font-family: sans-serif;
}
.description {
  border: 1px solid blue;
  border-radius: 0.5rem;
  padding: 1rem;
}
<div id="app">

  <p class="description" v-if="process.description">
    <template v-for="line in process.description?.split('\r\n')">
      {{line}}<br>
    </template>
  </p>
  
  <!-- v-html will trigger a XSS alert 
  <div v-html="process.description"></div>
  -->
  
  <!-- v-text will NOT trigger XSS alert, but no line breaks 
  <div v-text="process.description"></div>
  -->
  
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

1

As you said, You are getting description text straight from an API that means it's not directly coming from a user input. In that case you are good to go with v-html.

But if you still concern about the XSS vulnerability by using v-html, then you can do this with the help of v-for and splitting a string.

Live Demo :

new Vue({
  el: '#app',
  data: {
    description: 'This is a description for Process\r\nHere is no line break'
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <span v-for="(line, index) of description.split('\r\n')" :key="index">
    {{ line }}<br/>
  </span>
</div>

Comments

0

I think you should put your string in a <pre> tag instead https://www.w3schools.com/tags/tag_pre.asp .

<pre> respects line breaks etc and will avoid you doing replacement hacks.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.