Files

109 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "official-doc / WHATWG Fetch — CORS Protocol"
source_type: official-doc
url: https://fetch.spec.whatwg.org/
archive_url:
vendor: WHATWG
related_branches: [feature-api-contract-baseline, feature-security-operational-baseline]
related_projects: [ca-skeleton]
tags: [official-doc, ca-skeleton, security, networking, cors, fetch-spec]
status: raw
confidence: high
created: 2026-05-31
last_reviewed: 2026-05-31
---
# official-doc / WHATWG Fetch — CORS Protocol
> Layer: `raw/official-docs/` — WHATWG Fetch 표준(Living Standard)의 §3.3 CORS protocol 섹션 원문 발췌·출처 기록.
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 `source-summary-template` 형식으로 별도 작성. 원본은 raw에 영구 보관.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-api-contract-baseline]] | D13 — OPTIONS preflight 는 envelope 우회, resource metadata 는 envelope 따름. preflight request 의 식별 기준(OPTIONS method + `Access-Control-Request-Method` header)이 WHATWG Fetch §3.3.2 에 normative 하게 정의됨 |
| [[raw/branch-notes/feature-security-operational-baseline]] | D9 — CORS allowlist + credentials false default + max-age 600s + wildcard-with-credentials 금지. Fetch spec §3.3.5 가 1차 normative source. 기존 UNSUPPORTED_DECISION 라벨 해소 |
## 출처 / Source
- 원본 URL: https://fetch.spec.whatwg.org/
- 아카이브 URL: (미등록 — Living Standard, 항상 최신)
- 저자 / 조직: WHATWG (Anne van Kesteren et al.)
- 발행일: Living Standard (지속 갱신)
- 마지막 확인일: 2026-05-31
## 왜 저장했는지 / Why archived
`feature-security-operational-baseline` D9 (CORS allowlist + credentials + max-age + wildcard 금지) 가 `UNSUPPORTED_DECISION` 상태로 남아있었고, wildcard+credentials 조합 금지 및 `Access-Control-Max-Age` 의 의미를 normative 하게 정의하는 1차 표준 문서가 부재했음. WHATWG Fetch spec §3.3 이 browser-enforced CORS 동작의 유일한 normative 출처이며, `feature-api-contract-baseline` D13 (OPTIONS preflight 의 envelope 우회)의 preflight 식별 기준도 동일 섹션에서 정의됨.
## 핵심 인용 / Key quotes (verbatim, 5개)
> [§3.3 General] "The CORS protocol consists of a set of headers that indicates whether a response can be shared cross-origin."
> (원문 위치: line 5446 in fetched HTML)
> [§3.3.2 HTTP requests] "A CORS-preflight request is a CORS request that checks to see if the CORS protocol is understood. It uses `OPTIONS` as method and includes the following header: `Access-Control-Request-Method` — Indicates which method a future CORS request to the same resource might use."
> (원문 위치: line 54635472 in fetched HTML)
> [§3.3.3 HTTP responses — `Access-Control-Max-Age`] "Indicates the number of seconds (5 by default) the information provided by the `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers` headers can be cached."
> (원문 위치: line 55435546 in fetched HTML)
> [§3.3.5 CORS protocol and credentials — table note] "If credentials mode is `include`, then `Access-Control-Allow-Origin` cannot be `*`."
> (원문 위치: line 57365738 in fetched HTML)
> [§3.3.3 HTTP responses — `Access-Control-Allow-Credentials`] "Indicates whether the response can be shared when request's credentials mode is `include`."
> (원문 위치: line 55065508 in fetched HTML)
## Claims Extracted / 추출된 주장
> 이 자료가 **직접 말하는 것만** claim 으로 분리한다. 내 프로젝트에 적용한 결론은 여기 쓰지 않는다.
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| FETCH-CORS-C1 | CORS protocol 은 cross-origin response 공유 여부를 나타내는 HTTP header 집합이다 | [§3.3.1] "The CORS protocol consists of a set of headers that indicates whether a response can be shared cross-origin." | `official-standard` | 모든 browser cross-origin fetch | server 가 CORS 설정을 어떻게 구현해야 하는지 (server-side impl 방법은 spec 범위 밖) |
| FETCH-CORS-C2 | CORS-preflight request 는 `OPTIONS` method 를 사용하며 `Access-Control-Request-Method` header 를 포함한다 | [§3.3.2] "A CORS-preflight request is a CORS request that checks to see if the CORS protocol is understood. It uses `OPTIONS` as method and includes the following header: `Access-Control-Request-Method` — Indicates which method a future CORS request to the same resource might use." | `official-standard` | browser UA 가 preflight 를 전송하는 모든 경우 | server 가 preflight 에 어떻게 응답해야 하는지 (응답 필드는 §3.3.3에서 별도 정의) |
| FETCH-CORS-C3 | credentials mode 가 `include` 인 경우 `Access-Control-Allow-Origin``*` 일 수 없다 | [§3.3.5 table] "If credentials mode is `include`, then `Access-Control-Allow-Origin` cannot be `*`." | `official-standard` | browser UA 의 CORS check 알고리즘 | Spring CORS 설정이 이 조합을 startup 시 자동으로 거부하는지 (Spring-specific 동작은 별도 검증 필요) |
| FETCH-CORS-C4 | `Access-Control-Allow-Credentials` header 는 request 의 credentials mode 가 `include` 일 때 response 를 공유할 수 있는지를 나타낸다 | [§3.3.3] "Indicates whether the response can be shared when request's credentials mode is `include`." | `official-standard` | `credentials: include` 로 전송된 CORS request 에 대한 server response | CORS preflight 자체는 credentials 를 포함하지 않음 (preflight 의 credentials mode 는 `same-origin`) |
| FETCH-CORS-C5 | `Access-Control-Max-Age` 는 preflight 결과를 캐시할 수 있는 초(second) 수를 나타내며 기본값은 5초이다 | [§3.3.3] "Indicates the number of seconds (5 by default) the information provided by the `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers` headers can be cached." | `official-standard` | browser UA 의 CORS-preflight cache | server 측 max-age 600s 결정의 타당성 — 브라우저가 UA-imposed limit 을 상한으로 두기 때문에 실제 캐시 시간은 서버 설정과 다를 수 있음 (§4.8 "If max-age is greater than an imposed limit") |
### Strength 허용값 참조
- 모든 5개 claim: `official-standard` — WHATWG Living Standard (browser 구현의 normative 기준)
## Usage Boundaries / 적용 경계
### 이 자료가 직접 증명하는 것
- `FETCH-CORS-C1`: browser 가 cross-origin response 공유 여부를 CORS header 로 판단함
- `FETCH-CORS-C2`: browser UA 는 non-CORS-safelisted method 또는 non-CORS-safelisted request-header 가 포함된 요청에 대해 OPTIONS preflight 를 먼저 전송함. preflight = OPTIONS + `Access-Control-Request-Method` header 는 normative
- `FETCH-CORS-C3`: `credentials: include` + `Access-Control-Allow-Origin: *` 조합은 WHATWG spec 이 직접 금지 (browser 가 이 조합을 실패 처리)
- `FETCH-CORS-C4`: `Access-Control-Allow-Credentials: true` 가 없으면 `credentials: include` 요청의 응답이 공유되지 않음
- `FETCH-CORS-C5`: `Access-Control-Max-Age` 미설정 시 browser 기본값 = 5초. UA 는 자체 imposed limit 을 상한으로 적용 가능
### 이 자료가 증명하지 않는 것
- **server-side CORS allowlist 구현 방법**: Fetch spec 은 browser UA 의 동작을 정의. Spring `CorsConfiguration`, `WebMvcConfigurer.addCorsMappings()`, Spring Security `CorsFilter` 의 구현 방법은 Spring 벤더 문서에서 별도 확인 필요
- **Spring CorsConfiguration 이 startup 시 wildcard+credentials 조합을 자동으로 거부하는지**: `FETCH-CORS-C3` 는 browser 측 실패를 정의하며, server 측 Spring 의 startup-time validation 은 별도 source 필요 (`feature-security-operational-baseline` Claims To Verify 항목 유지)
- **gateway-level CORS 처리**: API gateway / WAF 가 app 보다 먼저 CORS 를 처리하는 경우 동작. Fetch spec 범위 밖
- **max-age 600s 가 production 에서 최적 값임**: `FETCH-CORS-C5` 는 기본값 5초와 UA 상한 존재를 증명하나, 600s 선택의 타당성은 별도 trade-off 결정
### 내 프로젝트에 적용하려면 추가 확인이 필요한 것
- Spring Security `CorsConfiguration.checkOriginPatterns()` 가 wildcard+credentials 조합에서 실제로 startup fail 또는 runtime reject 하는지 통합 테스트 필요 (`needs-confirmation` 상태 유지)
- `NimbusJwtDecoder` 와 별개로 Spring MVC `CorsFilter` 또는 `@CrossOrigin` 의 실제 동작 확인
- browser UA-imposed max-age limit (Chrome: 86400s, Firefox: 86400s) 과 서버 설정 max-age 600s 의 실효 관계 확인
## 메모 / Notes
- WHATWG Fetch spec 은 Living Standard 로 날짜 고정 버전이 없음. 인용 시 항상 "as of YYYY-MM-DD" 명시 권장
- §4.8 CORS-preflight fetch 알고리즘에 "If max-age is failure or null, then set max-age to 5" 가 명시 — browser default 5초는 spec normative
- §4.8 "If max-age is greater than an imposed limit on max-age, then set max-age to the imposed limit" — browser 가 server 설정값을 truncate 가능. 현재 Chrome/Firefox 상한 86400s (24h)
- `feature-security-operational-baseline` D9 의 `UNSUPPORTED_DECISION` 은 이 raw source 의 `FETCH-CORS-C3` 로 1차 normative 근거가 확보됨. D9 의 Decision Evidence Map 에 `FETCH-CORS-C3` 를 추가하고 `UNSUPPORTED_DECISION` 라벨 제거 권장 (별도 세션에서 branch-note 갱신)
## Related / 관련
- 같은 주제 RFC: RFC 6454 (The Web Origin Concept) — `Origin` header 정의의 원본 RFC
- Spring CORS 벤더 문서: `raw/official-docs/` 미등록 — 후속 fetch 필요
- 본 자료 인용 예정 wiki 요약: `wiki/concepts/cors-protocol` (생성 시)
- 관련 branch-note: [[raw/branch-notes/feature-security-operational-baseline]], [[raw/branch-notes/feature-api-contract-baseline]]