CSP 헤더 검증기

Content-Security-Policy 헤더 값을 붙여넣으면 지시문과 소스 값을 한 번에 검증합니다. unsafe-inline 같은 위험한 설정, default-src 미지정, 지시문 이름의 오타 등을 감지하고, 각 지시문에 허용된 소스를 시각적으로 보기 좋게 정리해 보여줍니다.

  • CSP는 보통 HTTP 응답 헤더로 전달되지만, <meta http-equiv="Content-Security-Policy"> 태그로도 설정할 수 있습니다(다만 report-uri 같은 일부 지시문은 이 경우 효과가 없습니다).
  • 운영 환경에 CSP를 바로 적용하기 전에, 위반 보고만 수집하는 Content-Security-Policy-Report-Only 헤더를 먼저 사용해 기존 기능에 미치는 영향을 확인하면 안전합니다.
  • 와일드카드(*)와 'unsafe-inline'은 개발을 편하게 해 주지만 CSP의 XSS 방어 효과 대부분을 무력화합니다. 배포 전에는 느슨한 정책을 반드시 좁혀야 합니다.
  • 같은 지시문을 두 번 작성해도 값이 합쳐지지 않고 첫 번째 항목만 적용됩니다. 소스를 추가하거나 덮어쓰려면 모두 하나의 지시문 안에 모아 두세요.
  • 브라우저 개발자 도구 콘솔은 차단된 리소스를 빨간색 "Refused to load..." 메시지로 그대로 표시하므로, 지나치게 엄격한 CSP를 디버깅할 때 가장 먼저 확인해야 할 곳입니다.

자주 묻는 질문

CSP는 브라우저에게 페이지에서 스크립트·이미지·스타일 등의 리소스를 어떤 출처에서 가져와도 되는지를 정확히 알려주는 장치입니다. 허용 목록에 없는 리소스(인라인 스크립트 포함)는 로드나 실행이 차단되므로, XSS 공격으로 공격자가 제어하는 스크립트가 실행될 위험을 크게 줄일 수 있습니다.

있습니다. nonce 소스('nonce-<임의값>')와 hash 소스('sha256-<해시값>') 모두 사용할 수 있습니다. 응답 헤더의 값과 일치하는 nonce 속성을 스크립트 태그에 추가하면, 그 특정 태그만 허용하면서 다른 승인되지 않은 인라인 스크립트는 계속 차단할 수 있습니다.

해당 리소스의 출처가 허용 목록에 없어 CSP가 차단한 것입니다. 브라우저 콘솔에 "Refused to load...because it violates the following Content Security Policy directive"와 같은 메시지가 표시되며 정확한 출처가 함께 나타나므로, 그 출처를 해당 지시문의 허용 목록에 추가하면 해결됩니다.

대부분의 경우 충분하지 않습니다. default-src는 명시적으로 설정하지 않은 지시문에 대한 대비책 역할만 합니다. script-src나 object-src처럼 위험도가 높은 지시문은 다른 대부분의 지시문보다 공격 표면이 훨씬 크므로 각각 명시적이고 엄격하게 설정해야 합니다.

둘 다 브라우저가 위반 보고서를 어디로 보낼지 지정하지만, report-uri는 보고서 전송 URL을 직접 지정하는 예전 방식의 지시문입니다. report-to는 더 새로운 Reporting API를 기반으로 하며, 별도의 Report-To 헤더에 정의된 이름 있는 그룹을 참조하는 방식입니다. 두 방식에 대한 브라우저 지원이 서로 다르므로, 호환성을 위해 둘 다 함께 지정하는 경우가 많습니다.
ツールくん

여담 ― CSP는 왜 생겨났을까 ― "이스케이프 철저히 하기"만으로는 막을 수 없었던 XSS의 역사

CSP(Content Security Policy)는 2004년경 Robert Hansen이 제안한 아이디어에서 출발해, 2008년 무렵부터 Mozilla 엔지니어 Brandon Sterne이 중심이 되어 공식 사양으로 다듬어졌고, 2012년 W3C의 첫 후보 권고안(Level 1)으로 정리되었습니다. 당시 XSS(크로스 사이트 스크립팅)는 웹 취약점 중에서도 특히 심각하게 여겨졌고, "모든 출력을 빠짐없이 이스케이프한다"는 개발자의 주의력에만 의존하는 방식으로는 충분히 견고한 방어가 될 수 없다는 반성에서, 브라우저 스스로가 스크립트의 허용 출처를 강제로 제한하는 다층 방어 체계로 CSP가 설계되었습니다.

CSP Level 2에서는 nonce와 hash를 이용한 인라인 스크립트 허용 방식이 도입되어, 'unsafe-inline'을 사용하지 않고도 특정 인라인 코드만 개별적으로 허용할 수 있게 되었습니다. 이어서 Level 3에서 추가된 'strict-dynamic'은 이미 신뢰된 스크립트가 동적으로 불러오는 하위 스크립트를 자동으로 신뢰하는 방식으로, 대규모 사이트에서 호스트 기반 허용 목록을 유지 관리하는 부담을 크게 줄여 줍니다.

Google은 자사의 대규모 서비스 전반에 nonce 기반의 엄격한 CSP를 지속적으로 도입해 왔으며, 이 과정에서 얻은 연구 결과를 공개했습니다. 그 내용은 호스트 이름 기반 허용 목록 방식의 CSP는 우회되기 쉬운 반면, nonce나 hash 기반 정책이 실제로는 훨씬 효과적이라는 것입니다. 이 결론은 오늘날 CSP 설계의 모범 사례로 널리 인용되고 있으며, 단순히 "어떤 값을 금지할 것인가"뿐 아니라 "애초에 어떤 방식으로 허용 목록을 구성할 것인가"라는 설계 판단이 중요함을 보여줍니다.

→ 모든 여담 보기