CSP(콘텐츠 보안 정책) 레시피
실무에서 정말 쓰는 구성을 담은 Content-Security-Policy 헤더 값 모음입니다. 엄격한 스타터부터 Google Fonts·애널리틱스·YouTube 임베드·nonce 기반 스크립트·클릭재킹 방어까지, 카드를 클릭해 정책을 복사한 뒤 Content-Security-Policy 헤더 값으로 설정하면 됩니다. 카드 위의 띠는 지시어 하나가 한 칸이고, 호박색 칸은 다시 살펴볼 가치가 있는 unsafe-* 소스를 포함한 지시어입니다.
엄격한 스타터(동일 출처만)
default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'동일 출처 + 이미지는 어디서든(https)
default-src 'self'; img-src 'self' data: https:; object-src 'none'; base-uri 'self'API 오리진 하나를 부르는 SPA
default-src 'self'; connect-src 'self' https://api.example.com; img-src 'self' data:; object-src 'none'Google Fonts 허용
default-src 'self'; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; object-src 'none'Google 애널리틱스 4
default-src 'self'; script-src 'self' https://www.googletagmanager.com; connect-src 'self' https://*.google-analytics.com https://*.analytics.google.com; img-src 'self' https://*.google-analytics.com; object-src 'none'YouTube 임베드 허용
default-src 'self'; frame-src https://www.youtube-nocookie.com https://www.youtube.com; img-src 'self' https://i.ytimg.com; object-src 'none'nonce + strict-dynamic 스크립트
script-src 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none'실용형: 인라인 스타일 허용
default-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self'http 하위 리소스를 https 로 승격
default-src 'self'; upgrade-insecure-requests클릭재킹 차단(프레이밍 금지)
frame-ancestors 'none'Report-Only 도입 스타터
default-src 'self'; report-uri /csp-report; report-to csp-endpoint자주 묻는 질문
- CSP 는 어디에 설정하나요?
- 가급적 HTTP 응답 헤더로 설정하세요. 서버·CDN·호스팅 설정에서 Content-Security-Policy: <값> 형태입니다. <meta http-equiv="Content-Security-Policy"> 태그도 대부분의 지시어에 동작하지만, frame-ancestors·report-uri·report-to 는 헤더 전용이라 이들이 들어간 레시피는 반드시 헤더로 설정해야 합니다.
- 사이트를 깨뜨리지 않고 도입하려면요?
- Content-Security-Policy-Report-Only 헤더(여기 Report-Only 레시피)로 시작하세요. 브라우저가 아무것도 차단하지 않고 위반만 보고합니다. 일주일쯤 보고를 지켜보며 사이트에 정말 필요한 소스를 추가한 뒤, 같은 값을 강제 헤더로 바꾸면 됩니다.
- nonce-{RANDOM} 자리표시자는 어떻게 쓰나요?
- {RANDOM} 을 응답마다 새로 생성한 base64 값으로 바꾸고, 같은 값을 각 스크립트 태그에 nonce="…" 로 넣습니다. strict-dynamic 과 함께 쓰면 내가 내보낸 스크립트(와 그것이 로드하는 것)만 정확히 허용되고 주입된 것은 전부 차단되어, 호스트 허용 목록을 관리하는 방식보다 강력합니다.
- 'unsafe-inline' 은 왜 호박색으로 표시되나요?
- 인라인 코드 허용은 XSS 공격이 파고드는 대표적인 구멍입니다. 주입된 <script> 나 style 속성이 내 코드처럼 실행되니까요. style-src 'unsafe-inline' 레시피는 아직 인라인 스타일을 주입하는 프레임워크가 많아 실용형으로 둔 것이고, 임시방편으로 취급하세요. 스크립트는 nonce 나 해시를 쓰는 편이 낫고, 그래서 여기 레시피에는 script-src 'unsafe-inline' 이 없습니다.