vue에서 v-html 디렉티브를 사용할 경우 eslint가 아래와 같은 에러를 뱉는다.
'v-html' directive can lead to XSS attack. --> 즉, 크로스 사이트 스크립팅 공격을 받을 수 있다는 것이다. v-html은 innerHTML을 기반으로 한 디렉티브이기 때문에 크로스 사이트 스크립팅 이슈가 발생하는 것이다.
React에서 dompurify
라이브러리를 통해 XSS를 방지했듯이, Vue에서는 vue-dompurify-html
을 통해 XSS를 방어할 수 있다.
사용법은 아래와 같이 vue-dompurify-html을 설치하고, main 파일에서 import 해준 뒤 작업중인 파일에서 v-html 대신 v-dompurify-html을 사용해주면 된다. (디렉티브명은 vue가 아니라 v임에 주의)
npm i vue-dompurify-html
// main.ts
import VueDOMPurifyHTML from 'vue-dompurify-html';
app.use(VueDOMPurifyHTML);
...
<p v-dompurify-html="~~~"></p>
...
아래는 테스트 코드이다.
const dompurifyTestHTML = ref('<svg/onload=alert(1)>');
<p v-html="dompurifyTestHTML">
<p v-dompurify-html="dompurifyTestHTML">
v-html 디렉티브의 경우 alert가 출력되지만, v-dompurify-html의 경우엔 출력되지 않는다. html tag를 html entity로 변경해주는 sanitize 처리가 됐기 때문에 XSS를 방지할 수 있는 것이다.
한편 iframe 태그에서 v-dompurify-html을 적용할 경우, 동영상이 렌더링되지 않는 문제가 추가로 발생했다. 구글링 결과 dompurify 라이브러리가 iframe 태그를 허용하지 않아서 발생하는 문제였다.
다만 아래와 같이 처리하면 iframe 태그를 허용하도록 할 수 있다.
// main.ts
import VueDOMPurifyHTML from 'vue-dompurify-html';
const vuePurifyHTMLConfig = {
ADD_TAGS: ['iframe'],
};
app.use(VueDOMPurifyHTML, {
default: vuePurifyHTMLConfig,
});
이후 iframe을 사용한다면 정상적으로 동영상이 렌더링되는 것을 확인할 수 있다.
참고 자료