CORS preflight는 브라우저의 응답 접근 정책이지 인증이나 CSRF 방어 전체가 아니다
OPTIONS 사전 요청 조건과 자격 증명 허용 범위, CORS가 막지 않는 요청을 구분한다.
발행·오류 제보: infostoa · 편집 기준
이 글의 개별 작성자와 전문 검토자 정보는 제공되지 않습니다.
preflight가 묻는 것
브라우저는 일부 교차 출처 요청 전에 OPTIONS 요청을 보내 서버가 요청 출처, 메서드, 헤더를 허용하는지 확인한다. Fetch 표준의 CORS 프로토콜이 정의하는 절차다. 모든 교차 출처 요청에 preflight가 생기는 것은 아니다. 메서드와 요청 헤더가 CORS safelist 조건을 벗어나거나, application/json처럼 safelisted content type이 아닌 유형을 쓰면 사전 요청이 필요할 수 있다. 브라우저는 응답의 Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers를 검토한 뒤 실제 요청을 보낼지 결정한다.
캐시와 실제 요청
성공 응답의 Access-Control-Max-Age는 브라우저가 preflight 결과를 캐시할 시간을 제안하지만, 브라우저별 상한과 별도 캐시 동작이 있어 지정한 시간만큼 반드시 유지된다고 볼 수 없다. preflight 캐시는 일반 HTTP 응답 캐시와 같은 것이 아니다. 서버는 실제 요청에도 인증·인가와 입력 검증을 적용해야 한다. preflight 응답이 허용되었다는 사실은 본 요청의 성공이나 데이터 접근 권한을 의미하지 않는다.
자격 증명과 출처 허용
쿠키나 HTTP 인증 정보를 포함하려면 클라이언트 요청의 credentials 설정과 서버의 Access-Control-Allow-Credentials: true가 함께 필요하며, 이 경우 Access-Control-Allow-Origin: *를 사용할 수 없다. 서버가 요청의 Origin을 그대로 반사해 허용하는 것은 안전한 allowlist가 아니다. 신뢰할 출처를 정확히 비교하고 동적 응답이면 적절한 Vary: Origin도 고려한다. CORS 응답 헤더는 브라우저가 스크립트에 응답을 공개할지 통제하지만, 서버 측 권한 확인을 대체하지 않는다.
OWASP 보안 전문가의 CSRF 관점
OWASP 보안 전문가 지침은 CORS를 범용 CSRF 방어 수단으로 취급하지 말라고 설명한다. 폼 제출 등 safelisted 요청은 preflight 없이 서버에 도달할 수 있고, CORS 차단은 응답을 읽지 못하게 할 뿐 요청 자체가 처리되지 않았음을 보장하지 않는다. 따라서 상태를 바꾸는 요청에는 CSRF 토큰, SameSite 쿠키 설정, Origin/Referer 검증 등 위협 모델에 맞는 서버 측 방어를 적용한다. 특히 브라우저가 자동으로 보내는 쿠키를 사용하는 서비스는 “CORS에서 출처를 제한했으니 CSRF가 없다”고 가정하면 안 된다.
개발자 점검 순서
브라우저 개발자 도구에서 OPTIONS와 실제 요청을 따로 확인하고, 허용 출처·메서드·헤더·credentials 조합을 테스트한다. 와일드카드나 Origin 반사, 실패한 preflight 뒤 서버가 상태 변경을 수행하는지 살핀다. 이 글의 보안 관점은 OWASP의 CSRF 분석에 근거하며, Fetch 표준은 프로토콜 동작을 정의한다. 두 출처의 역할은 서로 다르다.