HTTP 보안 헤더 검사기는 curl -I 출력이나 브라우저 DevTools의 응답 헤더 패널에서 복사해 붙여넣은 HTTP 응답 헤더를 읽고 A부터 F까지 등급을 매깁니다. 점수는 100점 만점이며 모든 점수의 근거가 표로 나옵니다. 열 개의 점검 항목마다 배점, 쉬운 말로 쓴 통과 조건, 결과, 판정에 쓴 헤더 값, 고칠 점을 알려 주는 짧은 설명이 있습니다.
배포, CDN 변경, 리버스 프록시 수정 직후에 설정한 헤더가 실제로 나가고 있는지 확인할 때 알맞습니다. 붙여넣은 텍스트를 검사하므로 공개 URL을 가져가는 스캐너로는 닿지 않는 스테이징 서버, 내부 호스트, 이전에 저장해 둔 응답도 점검할 수 있습니다.
서버에는 아무 요청도 보내지 않으며 텍스트는 브라우저 안에서 처리되고 이 도구가 서버로 전송하지 않습니다. 보고서에는 판정한 열 개 헤더의 값만 표시하고, 같은 블록에 있는 Set-Cookie 같은 쿠키와 토큰은 표시하지 않습니다. 빠른 점검이지 취약점 스캔이 아닙니다.
사용 방법
응답 헤더 가져오기
curl -I https://example.com을 실행하거나 DevTools의 Network 탭에서 문서 요청을 골라 응답 헤더를 복사합니다.HTTP/2 200같은 상태 줄이나 요청 줄이 섞여 있어도 건너뛰며 개수에 포함하지 않습니다.블록 붙여넣기
붙여넣는 즉시 등급이 갱신됩니다. 입력 한도는 256KiB이고 앞의 500줄만 읽습니다. 반복된 헤더는 합치고 접힌 연속 줄은 이어 붙입니다.
등급과 표 읽기
링에 등급 문자와 100점 만점의 점수, 읽은 헤더 수가 나옵니다. 표에서는 점검마다 통과·미흡·없음, 받은 점수와 배점, 발견된 값을 보여 줍니다.
고치고 다시 확인
서버나 CDN 설정을 바꾸고 헤더를 다시 가져와 붙여넣으면 등급이 어떻게 바뀌는지 볼 수 있습니다. 배점이 큰 항목부터 손보세요.
작동 원리
등급 계산 방식
각 항목에는 표시된 점수가 걸려 있습니다. 통과하면 전부, 값이 약하면 절반(소수점 버림), 헤더가 없으면 0점을 받습니다. CSP는 분석기 결과로 채점합니다. 오류와 경고가 없으면 25점, 경고 1건마다 3점이 깎이되 13점 아래로는 내려가지 않고, 오류가 하나라도 있으면 12점으로 제한되며 report-only도 12점입니다. 점수는 100점 만점의 합계이고 등급은 90점 이상 A, 75점 B, 60점 C, 40점 D, 그 미만 F입니다. Cache-Control은 참고용으로 표시할 뿐 점수에 넣지 않습니다.
| 점검 항목 | 배점 | 통과 조건 |
|---|---|---|
| Content-Security-Policy | 25 | 강제 정책(report-only 아님)이며 CSP 분석기에서 오류와 경고가 없음. 경고 1건당 3점 감점(최저 13점), 오류가 있으면 최대 12점 |
| Strict-Transport-Security | 20 | 숫자로 된 max-age가 정확히 하나이고 15552000초(180일) 이상이며, preload가 있으면 31536000 이상이고 includeSubDomains도 포함함 |
| X-Content-Type-Options | 10 | 쉼표로 나눈 첫 번째 값이 nosniff |
| 프레임 삽입 방지 | 10 | 구체적인 소스를 지정한 CSP frame-ancestors, 또는 X-Frame-Options의 DENY·SAMEORIGIN |
| Referrer-Policy | 10 | strict-origin-when-cross-origin, no-referrer처럼 전체 URL을 노출하지 않는 명시적 정책 |
| Permissions-Policy | 5 | camera=() 또는 geolocation=(self)처럼 올바른 정책 구문을 사용함 |
| Cross-Origin-Opener-Policy | 5 | 매개변수 앞의 값이 same-origin 또는 same-origin-allow-popups |
| Cross-Origin-Resource-Policy | 5 | same-origin, same-site, cross-origin 중 하나 |
| CORS 와일드카드 | 5 | Access-Control-Allow-Origin: *가 없음 |
| 기술 정보 노출 | 5 | 버전이 든 Server, X-Powered-By, X-AspNet-Version이 없음 |
각 헤더가 하는 일
Strict-Transport-Security(RFC 6797)는 max-age초 동안 그 호스트에는 HTTPS로만 접속하라고 브라우저에 알리며, includeSubDomains는 이를 하위 도메인까지 넓힙니다. X-Content-Type-Options: nosniff는 브라우저가 선언된 것과 다른 MIME 형식을 추측하지 못하게 합니다. Referrer-Policy는 다른 사이트로 보내는 페이지 URL의 양을 조절합니다. CSP는 스크립트, 스타일, 프레임 등을 불러올 수 있는 출처를 제한하며 그 frame-ancestors 지시문이 X-Frame-Options를 대체하는 최신 방식입니다. 이 검사기는 정책 자체를 CSP 분석기로 평가합니다.
교차 출처 헤더는 페이지를 격리합니다. Cross-Origin-Opener-Policy는 팝업이 내 창에 대한 참조를 유지하지 못하게 하고, Cross-Origin-Resource-Policy는 누가 리소스를 임베드할 수 있는지 정합니다. 와일드카드 Access-Control-Allow-Origin: *는 어떤 사이트의 스크립트든 응답을 읽게 하므로, 인증 정보 없는 공개 API에는 괜찮지만 쿠키나 토큰에 따라 달라지는 응답에는 잘못된 설정입니다.
붙여넣은 텍스트를 읽는 방식
각 줄을 헤더 이름, 콜론, 값으로 읽으며 이름은 올바른 HTTP 토큰이어야 하고 소문자로 비교합니다. #으로 시작하는 줄, HTTP 상태 줄, GET / HTTP/1.1 같은 요청 줄, 콜론으로 시작하는 의사 헤더는 건너뛰며 몇 줄을 건너뛰었는지 보고서에 표시합니다. 여러 번 나온 헤더는 쉼표로 구분한 하나의 값으로 합치고, 공백으로 시작하는 줄은 앞 헤더의 연속으로 봅니다.
실제 예시
HTTP/2 200
content-type: text/html; charset=utf-8
strict-transport-security: max-age=63072000; includeSubDomains
x-content-type-options: nosniff
content-security-policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
referrer-policy: strict-origin-when-cross-origin
permissions-policy: camera=()
cross-origin-opener-policy: same-origin
cross-origin-resource-policy: same-origin
cache-control: no-store등급 A, 100 / 100 (헤더 9개 읽음, 상태 줄 1개 건너뜀)
점수가 걸린 열 개 항목 모두 통과, Cache-Control: no-store (점수 없음)프레임 삽입 방지는 CSP의 frame-ancestors 'none'으로 통과하므로 X-Frame-Options가 필요 없습니다.
HTTP/1.1 200 OK
Server: nginx/1.18.0
X-Frame-Options: ALLOWALL
Access-Control-Allow-Origin: *
Set-Cookie: session=abc; HttpOnly등급 F, 9 / 100 (헤더 4개 읽음, 상태 줄 1개 건너뜀)
프레임 삽입 방지: 미흡, 5 / 10 (ALLOWALL)
CORS 와일드카드: 미흡, 2 / 5 (*)
기술 정보 노출: 미흡, 2 / 5 (Server: nginx/1.18.0)
CSP, HSTS, nosniff, Referrer-Policy, Permissions-Policy, COOP, CORP: 없음ALLOWALL은 올바른 값이 아니어서 프레임 항목은 절반만 받습니다. 쿠키 값은 표시하지 않습니다.
Strict-Transport-Security: max-age=0
Content-Security-Policy: script-src 'unsafe-inline'
X-Content-Type-Options: nosniff
Referrer-Policy: unsafe-url
x-frame-options: DENY등급 D, 57 / 100 (헤더 5개 읽음)
CSP: 미흡, 12 / 25 (분석기가 오류 보고)
HSTS: 미흡, 10 / 20 (max-age=0은 HSTS를 끔)
nosniff: 통과, 10 / 10
프레임: 통과, 10 / 10
Referrer-Policy: 미흡, 5 / 10 (unsafe-url)
Permissions, COOP, CORP: 없음
CORS와 기술 정보 노출: 통과, 10 / 10있는지만 보는 단순한 점검이라면 이 헤더들은 모두 통과했을 것입니다. 여기서는 max-age=0, 'unsafe-inline'이 든 스크립트 정책, unsafe-url이 각각 배점의 절반을 잃습니다.
strict-transport-security: max-age=31536000; includeSubDomains
content-security-policy: default-src 'self'
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin등급 C, 66 / 100 (헤더 4개 읽음)
CSP: 미흡, 16 / 25 (분석기 경고 3건)
HSTS 20 / 20, nosniff 10 / 10, Referrer-Policy 10 / 10, CORS 5 / 5, 기술 정보 노출 5 / 5
프레임: 없음, 0 / 10
Permissions-Policy, COOP, CORP: 없음분석기가 object-src, base-uri, frame-ancestors가 없다고 경고하므로 CSP가 3점씩 깎입니다. object-src 'none'; base-uri 'none'; frame-ancestors 'none'을 더하면 25점을 모두 받고 프레임 점검도 통과해 85점, B등급이 됩니다.
GET https://example.com/ HTTP/1.1
Host: example.com
# comment
Accept: */*등급 F, 10 / 100 (헤더 2개 읽음, 요청 줄 1개 건너뜀)
여덟 개 항목 없음, CORS와 기술 정보 노출은 통과요청 줄은 GET https라는 이름의 헤더로 읽히지 않고 건너뜁니다. 10점은 헤더가 없을 때 통과하는 두 항목에서만 나옵니다. 요청이 아니라 응답을 붙여넣으세요.
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
referrer-policy: no-referrer-when-downgrade
server: nginx/1.18.0등급 D, 52 / 100 (헤더 5개 읽음)
HSTS 20 / 20, nosniff 10 / 10, 프레임 10 / 10, CORS 5 / 5
Referrer-Policy: 미흡, 5 / 10
기술 정보 노출: 미흡, 2 / 5
CSP, Permissions-Policy, COOP, CORP: 없음CSP가 없으면 그것만으로 25점이 깎여서, 전송과 프레임 관련 헤더가 좋은 사이트도 D에 머물 수 있습니다.
자주 하는 실수
높은 등급은 보안 감사가 아님
등급은 응답 헤더만 평가합니다. 주입 취약점, 쿠키 플래그, 오래된 소프트웨어, 접근 제어에 대해서는 아무것도 말해 주지 않습니다. 설정 점검표로 쓰세요.
한 URL의 헤더가 모든 URL의 헤더는 아님
HTML 페이지, API 응답, 정적 파일, 오류 페이지의 헤더는 서로 다를 수 있습니다. 관심 있는 응답을 가져오고 리디렉션과 404도 확인하세요.
HSTS에는 부작용이 있음
브라우저가 긴
max-age를 한 번 보면 그 호스트에 평문 HTTP를 쓰지 않으며preload는 사실상 되돌릴 수 없습니다. 값을 점진적으로 올리고 모든 하위 도메인이 HTTPS를 지원할 때만includeSubDomains를 추가하세요.report-only는 강제가 아님
Content-Security-Policy-Report-Only만 보내는 사이트는 CSP 배점의 절반을 받습니다. 정책이 위반을 보고만 하고 아무것도 차단하지 않기 때문입니다.요청이 아니라 응답을 붙여넣기
Host,Accept,Authorization같은 요청 헤더는 일반 헤더로 읽히며 응답에는 나오지 않습니다. 건너뛰는 것은 요청 줄 자체뿐입니다.
자주 묻는 질문
도구가 내 사이트에 요청을 보내나요?
아니요. 붙여넣은 텍스트만 읽습니다. 그래서 스테이징 서버나 저장해 둔 응답도 점검할 수 있습니다.
등급은 어떻게 계산하나요?
열 개 항목의 합이 100점입니다. 통과는 배점 전부, 약한 값은 절반, 헤더가 없으면 0점입니다. CSP만 예외로, 분석기 경고 1건마다 25점 중 3점이 깎이되 13점 아래로는 내려가지 않고 오류가 있으면 12점으로 제한됩니다. 90점 이상 A, 75점 B, 60점 C, 40점 D, 40점 미만 F입니다. 배점은 페이지의 표와 이 글에 모두 나와 있습니다.
max-age=0은 왜 통과가 아닌가요?
max-age가 0이면 브라우저가 그 호스트의 HSTS를 잊게 되므로 보호와 정반대입니다. 이 도구의 기본 통과 기준은 Mozilla의 최소 지침에 맞춘 15552000초(180일)입니다. 헤더가 preload를 내세우면 31536000초(1년) 이상이고 includeSubDomains도 있어야 하며, 빠지면 경고합니다. 프리로드 목록도 같은 조건을 요구합니다.
frame-ancestors가 있으면 X-Frame-Options가 필요한가요?
아니요. 구체적인 소스를 지정한 CSP frame-ancestors만으로 프레임 점검을 통과합니다. X-Frame-Options를 함께 두는 것은 아주 오래된 브라우저에만 도움이 됩니다.
쿠키 값이나 토큰이 표시되나요?
아니요. 보고서에는 판정한 열 개 헤더의 값만 표시하고 Set-Cookie는 절대 표시하지 않습니다. 붙여넣은 텍스트는 브라우저 안에 머뭅니다.
Cache-Control은 왜 점수에 넣지 않나요?
알맞은 캐시 정책은 응답마다 다릅니다. 비공개 페이지에는 no-store, 해시가 붙은 정적 자산에는 긴 캐시가 맞습니다. 표에는 참고용으로 값만 보여 줍니다.
더 깊이 읽기
마지막 업데이트:
