크로스 사이트 스크립팅(XSS)은 가장 흔한 웹 앱 취약점 중 하나로 공격자가 웹사이트에 악성 클라이언트 사이드 코드를 삽입할 수 있도록 하는 보안 취약점 공격이다.
HTML 코드를 사이트에 렌더링 하기 위해서는 어떻게 해야할까? Vue.js 의 경우, v-text
나 {{}}
는 있는 그대로 문자열을 렌더링하기 때문에 HTML 코드 형태로 렌더링하기 위해서는 v-html
을 사용해야 한다.
그러나 v-html
은 innerHTML
기반이기 때문에 XSS 위협이 있다.
vue.js 공식 문서에도 v-html을 사용하기 위해서는 신뢰할 수 있는 콘텐츠에서만 사용하라는 안내문구가 있으며,
eslint를 적용한 IntelliJ에서도 경고를 보여주는걸 확인할 수 있다.
물론 innerHTML 기반이기 때문에 <script></script>
와 같은 누구나 알 수 있는 코드는 삭제되지만 이외의 <img srcset=",,,,,x">
와 같은 코드는 바로 실행되는것을 알 수 있다.
html을 보여주지 않을 수 없으니 그렇다면 어떻게 적용해야할까?
해결 방법을 찾아보니 v-dompurify-html, santize-html 와 같은 라이브러리로 쉽게 해결할 수 있었다. 그 중 2024년 1월 기준 가장 많이 사용하고 있는 dompurify 를 적용한 v-dompurify를 사용해서 v-html 필터링을 적용했다.
// vue 2 이하
npm install vue-dompurify-html@vue-legacy
// vue 3 이상
npm install vue-dompurify-html
// main.ts
import Vue from 'vue';
import App from './App.vue'
import VueDOMPurifyHTML from 'vue-dompurify-html';
Vue.use(VueDOMPurifyHTML);
new Vue({
render: h => h(App),
}).$mount('#app')