처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.04.28 23

SVG 새니타이징의 함정: Scratch 팀이 마주한 보안 지옥

Hacker News 원문 보기

SVG가 그렇게 위험한 파일이라고요?

어린이 코딩 교육 플랫폼 "Scratch" 아시죠? MIT 미디어랩에서 만든 거고, 전 세계 수천만 명의 아이들이 블록 코딩으로 게임이랑 애니메이션을 만드는 곳이에요. 이 Scratch 팀의 한 개발자가 SVG 파일을 안전하게 정화(sanitize)하는 게 얼마나 끔찍한 일인지 솔직하게 풀어놓은 글이 개발자 커뮤니티에서 회자되고 있어요.

잠깐 SVG가 뭔지부터요. SVG는 Scalable Vector Graphics의 약자로, 이미지를 픽셀이 아니라 "이 점에서 저 점으로 선을 긋고, 여기에 원을 그려라" 같은 명령어로 표현하는 벡터 이미지 포맷이에요. PNG나 JPG가 사진처럼 픽셀 덩어리라면, SVG는 텍스트 기반의 XML 문서예요.

바로 이 "텍스트 기반"이라는 점이 SVG를 보안 측면에서 악몽으로 만들어요. 일반 이미지 파일은 그냥 픽셀 데이터지만, SVG는 안에 JavaScript도, 외부 리소스 참조도, 다른 SVG 임베드도 다 가능한 거의 작은 웹페이지나 마찬가지거든요.

Scratch 팀이 왜 이걸 해야 했나

Scratch는 사용자(주로 아이들!)가 직접 그림을 그리거나 업로드해서 프로젝트에 쓸 수 있게 해줘요. 이때 사용자가 올린 SVG를 다른 사용자에게 보여주려면, 그 SVG가 악성 코드를 품고 있지 않다는 걸 보장해야 해요. 이게 새니타이징이에요. 위험한 부분을 잘라내고 안전한 부분만 남기는 거죠.

그런데 "위험한 부분"이 너무 많아요. 글쓴이가 정리한 공격 벡터를 보면 정신이 아득해져요.

구체적으로 뭐가 위험한가

첫째, 스크립트 실행. <script> 태그가 SVG 안에 들어갈 수 있어요. 이걸 페이지에 인라인으로 넣으면 그냥 XSS(Cross-Site Scripting)예요. 다른 사용자의 쿠키, 세션을 다 털 수 있죠. 이건 그나마 잘 알려진 거라 막기 쉬워요.

둘째, 이벤트 핸들러. <circle onclick="alert(1)">처럼 거의 모든 SVG 요소에 onload, onclick, onmouseover 같은 이벤트 속성을 붙일 수 있어요. on으로 시작하는 속성을 전부 제거해야 하는데, 대소문자 구분이 없거나 인코딩으로 우회할 수 있어서 단순 문자열 검사로는 막기 어려워요.

셋째, 외부 참조. <image href="https://attacker.com/track.png"> 같이 외부 리소스를 부르면, 단순 트래킹부터 사용자 IP 수집까지 가능해요. 더 무서운 건 <use href="#malicious">로 같은 문서 내 요소를 참조해서 우회하는 기법이에요.

넷째, CSS 인젝션. <style> 태그 안에 @import url("...") 같은 걸 넣으면 외부 CSS를 불러올 수 있고, CSS 자체로도 데이터 유출이 가능해요. 더 나아가 일부 브라우저에서는 CSS 안에 expression()이나 -moz-binding 같은 비표준 기능으로 코드 실행이 됐던 역사도 있어요.

다섯째, 외부 엔티티(XXE). SVG는 XML이라서 DOCTYPE 선언으로 외부 엔티티를 정의할 수 있어요. 잘못 파싱하면 서버의 로컬 파일을 읽어버려요.

여섯째, 그리고 끝없는 우회. Scratch 팀이 정말 고통받은 부분인데요, 다 막았다고 생각하면 누군가 또 새 우회법을 가져와요. SVG 안의 <foreignObject>로 HTML을 임베드하기, CDATA 섹션 안에 스크립트 숨기기, 유니코드 이스케이프, 인코딩 변환... 끝이 없어요.

그래서 어떻게 풀어야 하나

글쓴이가 강조하는 건 "블랙리스트가 아닌 화이트리스트" 접근이에요. 위험한 걸 빼는 게 아니라, 안전하다고 100% 확신하는 것만 통과시키고 나머지는 다 버리는 방식이죠. 태그도, 속성도, 속성값도 모두 화이트리스트로.

실무적으로는 DOMPurify 같은 잘 검증된 라이브러리를 쓰는 게 가장 안전해요. 직접 정규식으로 짜겠다는 생각은 거의 100% 뚫려요. 또 하나는 SVG를 <img> 태그로만 보여주기예요. <img src="data:image/svg+xml,..."> 형태로 띄우면 브라우저가 스크립트를 실행하지 않거든요. 다만 인터랙티브 SVG가 필요하다면 이 방법은 못 써요.

업계 맥락

이 문제는 Scratch만의 일이 아니에요. GitHub은 한때 SVG 미리보기에서 XSS가 터졌고, Discord, Slack, Notion 같은 곳들도 비슷한 일을 겪었어요. 사용자 콘텐츠를 받는 모든 서비스의 영원한 숙제죠. 최근에는 Cloudflare가 자사의 새니타이저를 오픈소스로 풀거나, Google이 "Sanitizer API"라는 브라우저 표준을 추진하면서 이걸 플랫폼 차원에서 풀려는 시도도 있어요.

한국 개발자에게 주는 시사점

사용자가 이미지를 올릴 수 있는 서비스를 만들고 있다면, "PNG/JPG만 받고 SVG는 받지 마세요"가 가장 단순한 해법이에요. 꼭 SVG가 필요하다면 DOMPurify나 svg-sanitizer 같은 라이브러리를 거치고, CSP(Content Security Policy)로 한 번 더 방어선을 쳐두세요. 이미지 도메인을 별도 서브도메인으로 분리하는 것도 쿠키 탈취 위험을 줄여줘요.

그리고 보안은 "내가 직접 짜는 게 멋있어" 영역이 아니라는 걸 다시 한번 생각해보세요. 구글, 메타 같은 회사들이 십수 년 동안 패치해온 라이브러리를 쓰는 게 거의 항상 정답이에요.

마무리

SVG 새니타이징은 단순해 보이지만 끝없는 우회와 싸우는 일이에요. 사용자 콘텐츠를 받는 한, 우리는 영원히 공격자보다 한 발 앞서가야 해요. 여러분의 서비스에서는 사용자 업로드 파일을 어떻게 검증하고 계세요?


🔗 출처: Hacker News

이 뉴스가 유용했나요?

TTJ 코딩클래스 정규반

월급 외 수입,
코딩으로 만들 수 있습니다

17가지 수익 모델을 직접 실습하고, 1,300만원 상당의 자동화 도구와 소스코드를 받아가세요.

144+실전 강의
17개수익 모델
4.9수강생 평점
정규반 자세히 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.