I'm trying to work with v-html without xss issues. I think I am using v-html in a safe way. Could you take a look to validate that I am avoiding xss issues?
Users would input a text field ("words"). This would be stored in a database. When the content is pulled from the database, the javascript would render words between two tags "/b/" as bolded words.
Here is a codepen: https://codepen.io/kiggs1881/pen/KKxEJbx
Here is the code:
const VueApp = defineComponent({
setup() {
const words = ref("Hello /b/World/b/, I am a
/b/friend/b/.")
const parseWords = (text) => {
return text
.split("/b/")
.map((part, i) => {
return i % 2 ? `<strong>${part}</strong>` : part;
})
.join(" ");
}
return {
parseWords,
words
}
},
template: `
<input v-model="words">
<div v-html="parseWords(words)"></div>`
})
I understand that v-html is vulnerable to xss attacks, but I'm hoping that the limited way I propose to use it eliminates the possibility of attacks.
As per looking into your code, I would say Yes. It's vulnerable to XSS
attack.
As you are taking an input from user. So in that case user can enter any malicious tags or script through he input box and while rendering/saving that data will attack on your application.
Solution : You should sanitize the user input after receiving and before submitting that to database. To achieve this you can remove the blacklist characters from the string.
Just for a better understanding, I am adding a working demo in Vanilla JavaScript (You can make it work as per Vue), Also, you can add more invalid characters in the blacklist regex.
const blackListRegex = /(<[^>]+>|<[^>]>|<\/[^>]+>)/ig
function sanitizeInput() {
const inputValue = document.getElementById('words').value;
console.log(inputValue.replace(blackListRegex, '')); // This will be the final string which you can store in the database and render in the HTML template.
}
<input type="text" name="words" id="words" onBlur="sanitizeInput()"/>