문서 작업 가이드

배포 전에 Content-Security-Policy 헤더 분석하기

배포된 CSP 필드를 캡처하고 시행과 Report-Only를 구분한 뒤, first-wins 중복과 누적 정책을 검토하고 운영 규칙을 바꾸기 전에 실제 브라우저 동작을 시험합니다.

작성 및 검수 게시일: 검토일:

이 작업 흐름을 검증한 방법

“image data:를 script 위험으로 오해하지 않고 nonce 정책 검토” 문서 입력을 CSP 헤더 분석기에 그대로 넣었습니다. 수행 순서는 “공유 전 캡처 최소화”, “유효 문맥에서 source 해석”였고 브라우저 결과를 예시 출력과 대조했습니다. 실패 경계는 “엣지가 아닌 origin 응답 검토”, “무시되는 중복 편집” 두 항목으로 나눠 검토했습니다.

파서는 nonce와 'strict-dynamic'의 관계를 유지했고 고위험 항목은 0건으로 판정했으며, img-src data:는 스크립트 위험이 아니라 이미지 동작에 따라 정당화할 검토 항목으로 표시했습니다.

문제 상황

Content-Security-Policy는 하나의 단순한 허용 목록이 아닙니다. 응답에는 시행 필드, Report-Only 필드, 쉼표로 구분된 여러 정책, 애플리케이션·리버스 프록시·CDN이 각각 추가한 반복 필드가 함께 있을 수 있습니다. 정책 하나에서는 같은 이름의 첫 directive가 유효하고 뒤의 중복은 무시되지만, 서로 다른 정책의 제한은 누적 적용됩니다. unsafe-inline 같은 토큰도 유효 directive, nonce나 hash, strict-dynamic, 브라우저 호환성 문맥 없이 단정적으로 채점할 수 없습니다. 긴 헤더 문자열만 보고 수정하면 실제로 차단하지 않은 정책을 느슨하게 만들거나, 브라우저가 무시하는 중복을 편집하거나, 다른 경로의 실패를 해결하려고 광범위한 source를 허용할 수 있습니다. 제대로 된 검토는 최종 배포 응답을 캡처하고, 불필요한 비밀값을 제거하고, 정확한 CSP 필드 하나를 파싱하고, 결과를 브라우저 위반과 연결하고, 영향을 받는 경로와 리소스 종류를 시험한 뒤 설정 전파 후 엣지 응답을 다시 캡처해야 합니다.

공식 출처와 표준

다음 공식 문서는 이 작업 흐름에서 다루는 형식과 보안 경계의 기준입니다. 도구별 실행 검증은 위에 별도로 기록합니다.

이럴 때 사용하세요

  • 콘솔이나 CSP 보고서가 차단된 script, image, font, frame, worker, form action 또는 API 연결을 가리킬 때
  • Content-Security-Policy-Report-Only 후보를 시행 정책으로 바꾸려 할 때
  • 애플리케이션, 프록시와 CDN이 중복 필드나 directive를 추가할 가능성이 있을 때
  • nonce, hash, strict-dynamic, wildcard, data:, blob: 또는 HTTP source를 문맥에 맞게 검토해야 할 때
  • 출시 체크리스트에 최종 배포 응답의 변경 전후 증거가 필요할 때

단계

  1. 1단계

    마지막 응답 필드 캡처

    문제가 발생한 정확한 경로를 DevTools에서 열거나 응답 하나에는 curl -I, redirect가 중요하면 curl -IL을 사용합니다. CDN과 리버스 프록시가 수정한 뒤의 마지막 Content-Security-Policy 또는 Content-Security-Policy-Report-Only 필드를 복사합니다.

  2. 2단계

    공유 전 캡처 최소화

    CSP 필드 이름과 쉼표·세미콜론을 포함한 전체 값은 유지합니다. 쿠키, Authorization, 서명된 report endpoint 매개변수, 검토에 필요 없는 내부 hostname과 다른 응답 헤더는 제거합니다.

  3. 3단계

    정책과 첫 directive 파싱

    CSP 헤더 분석기에 CSP 필드 하나를 붙여넣습니다. 시행 상태, 정책 수, 인식·미인식 directive를 확인하고 중복 결과를 봅니다. 한 정책의 뒤쪽 중복은 앞의 값을 덮지 않습니다.

  4. 4단계

    유효 문맥에서 source 해석

    nonce, hash, strict-dynamic과 더 구체적인 directive fallback을 고려해 unsafe-inline을 검토합니다. script·object wildcard를 의도된 image data:보다 우선 처리하고, 잘못되거나 레거시인 값은 이유를 확인한 뒤 수정합니다.

  5. 5단계

    증상을 브라우저 증거와 연결

    위반을 만든 경로와 동작을 재현합니다. script·style 실패는 유효 fallback chain, API와 WebSocket은 connect-src, frame은 frame-src 또는 frame-ancestors, worker는 worker-src, 제출은 form-action과 연결합니다.

  6. 6단계

    가장 좁은 정책 소유자 수정

    실제 유효 directive를 소유한 애플리케이션, 미들웨어, 프록시 또는 CDN 규칙을 수정합니다. 적절하면 nonce, hash, 정확한 신뢰 origin을 사용하고 출시 중 Report-Only 관찰을 유지하며 콘솔을 조용하게 하려고 광범위한 예외를 추가하지 않습니다.

  7. 7단계

    경로 재시험과 엣지 재캡처

    지원 브라우저에서 정상·오류·인증·embed·worker·서드파티 흐름을 시험하고 위반량을 확인합니다. 캐시와 설정 전파 뒤 마지막 응답을 다시 캡처하고 정리된 변경 전후 필드를 출시 기록에 남깁니다.

예시

image data:를 script 위험으로 오해하지 않고 nonce 정책 검토

입력

Content-Security-Policy: default-src 'self'; script-src 'nonce-AbCd12_-' 'strict-dynamic'; style-src 'self'; img-src 'self' https: data:; connect-src 'self' https://api.example.com; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; report-to csp-endpoint

출력

시행 상태: 시행
정책: 1
고위험 결과: 0
검토: img-src data:는 정보이며 이미지 동작상 필요성을 확인해야 합니다. 예시 nonce로 런타임 nonce 생성이나 요소 일치를 증명할 수 없습니다.

흔한 실수

엣지가 아닌 origin 응답 검토

리버스 프록시나 CDN은 CSP 필드를 추가·결합·교체할 수 있습니다. 애플리케이션 서버 값만 보면 브라우저가 받은 응답과 다를 수 있습니다.

무시되는 중복 편집

한 정책에서는 같은 이름의 첫 directive가 유효합니다. 뒤의 중복만 바꾸면 브라우저 동작은 그대로이고 설정만 더 이해하기 어려워질 수 있습니다.

Report-Only를 시행으로 취급

Report-Only는 차단하지 않고 관찰 결과만 만듭니다. 깨끗한 후보도 시행 필드로 배포하고 검증하기 전에는 페이지를 보호하지 않습니다.

여러 정책을 선택지로 해석

요청은 모든 시행 정책을 통과해야 합니다. 정책을 하나 더 추가하면 동작을 유지하거나 더 제한할 수 있을 뿐 기존 제한을 느슨하게 만들 수 없습니다.

광범위한 예외로 보고서 숨기기

*, unsafe-inline, unsafe-eval, data: 또는 scheme 전체를 추가하면 증상은 사라져도 권한 범위가 커집니다. 정확한 의존성과 소유자를 먼저 추적하세요.

자주 묻는 질문

두 번째 script-src를 바꿔도 동작이 달라지지 않는 이유는 무엇인가요?

CSP 파싱 규칙은 한 정책에서 같은 이름의 첫 directive를 유지하고 뒤의 중복을 무시합니다. 중복을 제거하고 실제 첫 directive를 만드는 계층을 수정하세요.

두 번째 CSP 정책이 첫 정책을 느슨하게 만들 수 있나요?

아니요. 시행 정책은 누적 적용되므로 리소스가 모든 관련 정책을 통과해야 합니다. 추가 정책은 권한을 유지하거나 더 제한할 수 있습니다.

unsafe-inline 문구가 있으면 항상 활성인가요?

아닙니다. 관련 유효 source list의 nonce나 hash는 unsafe-inline이 모든 inline 동작을 허용하지 못하게 하고, strict-dynamic도 최신 script 처리를 바꿉니다. 호환성 시험은 필요합니다.

모든 정책에 default-src가 있어야 하나요?

반드시 그렇지는 않습니다. default-src는 fetch directive의 fallback입니다. 의도적으로 명시적 범위를 썼다면 생략할 수 있지만 앱의 모든 리소스 종류와 fallback chain을 검토해야 합니다.

분석기가 사이트를 가져오거나 런타임 nonce를 검증하나요?

아니요. 제한된 붙여넣기 텍스트를 로컬에서 파싱합니다. 배포 필드, nonce 생성, 요소 일치, 보고서와 경로 동작은 DevTools, curl, 브라우저 시험과 서버 검토로 확인하세요.

출시 검토에는 어떤 증거를 남겨야 하나요?

정리한 마지막 응답 필드, 파싱 보고서, 대표 위반 표본, 시험한 경로와 브라우저, 설정 소유자, 배포 시각, 전파 후 재캡처를 보관하세요.