flawopen.com/JavaScript의 XSS/dangerouslySetInnerHTML
React의 dangerouslySetInnerHTML은 안전할까?
일반 JSX는 텍스트가 텍스트로 남는 라벨 프린터와 같습니다. dangerouslySetInnerHTML은 문자열을 HTML로 해석하는 인쇄기로 전환합니다. 공격자가 제어하는 내용이 문자열에 들어 있으면 브라우저가 이를 활성 마크업으로 처리할 수 있습니다. 명시적으로 신뢰하거나 정확한 HTML 컨텍스트에 맞게 정제한 HTML에만 이 출력 지점을 사용하세요.
일반 JSX에는 왜 필요하지 않을까
function Comment({ html }) {
return <p dangerouslySetInnerHTML=
{{ __html: html }} />;
}
function Comment({ text }) {
return <p>{text}</p>;
}
dangerouslySetInnerHTML은 언제 적절할까?
일반 React 자식 요소로 표현할 수 없는 제한된 리치 텍스트 형식을 제품에서 보존해야 할 때만 사용하세요. CMS, 편집기, Markdown 렌더러라고 해서 자동으로 신뢰할 수 있는 것은 아닙니다. 저장된 콘텐츠와 렌더러 출력에도 신뢰할 수 없는 마크업이 들어갈 수 있습니다. 허용할 요소와 속성을 정하고 DOMPurify 같은 유지 관리되는 HTML 정제 라이브러리로 처리한 뒤 결과를 이 지점에 바로 전달하세요.
올바른 사용법
dangerouslySetInnerHTML에 값을 전달하기 직전에 DOMPurify 같은 유지 관리되는 라이브러리로 정제하세요. 정규식으로 HTML을 정제하지 마세요. 정제한 문자열을 이후에 변경하면 보장이 무효화될 수 있으므로 피하세요. 정제 라이브러리와 파서 환경을 최신 상태로 유지하세요.
알려진 태그만 차단하는 목록으로는 부족합니다. 속성, URL 필드, 네임스페이스, 파서 동작도 위험 요인이 될 수 있습니다. 기능에 필요한 최소한의 요소와 속성만 허용하도록 정하고 그 정책에 맞게 정제기를 설정하세요. 링크와 URL 속성은 제품에서 허용하는 목적지를 기준으로 별도 검토하세요.
코드베이스 확인 방법
grep -rn "dangerouslySetInnerHTML" --include="*.jsx" --include="*.tsx" .자주 묻는 질문
렌더러와 설정에 따라 다릅니다. 원시 HTML을 허용하는지, 출력물을 정제하는지 확인하세요. Markdown 변환만으로 HTML이 안전해지지는 않습니다.
그렇습니다. v-html도 프레임워크의 일반 텍스트 보간을 거치지 않고 HTML을 브라우저에 전달합니다. HTML 출력 지점으로 보고 적절한 정책으로 신뢰할 수 없는 내용을 정제하세요.