109 lines
9.8 KiB
Markdown
109 lines
9.8 KiB
Markdown
---
|
||
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 5463–5472 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 5543–5546 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 5736–5738 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 5506–5508 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]]
|