1. 소개
이 섹션은 규범적인 것이 아닙니다.
웹 애플리케이션은 사용자가 오프라인일 때 기능을 제공하고, 온라인일 때 성능을 높이기 위해 사용자의 컴퓨터에 데이터를 로컬로 저장합니다. 이러한 로컬 캐시는 사용자와 개발자 모두에게 큰 이점을 제공하지만, 동시에 위험도 수반합니다.
사용자의 데이터는 민감하며 가치가 있으므로, 웹 개발자는 이를 보호하기 위해 합리적인 조치를 취해야 합니다. 한 가지 조치는 데이터를 저장하기 전에 암호화하는 것이고, 또 다른 조치는 더 이상 필요하지 않을 때 사용자 기기에서 데이터를 삭제하는 것입니다(예: 사용자가 애플리케이션에서 로그아웃하거나 계정을 삭제할 때).
사이트 제작자는 JavaScript를 통해 여러 저장 메커니즘의 데이터를 삭제할 수 있지만, 일부는 신뢰성 있게 다루기가 어렵습니다. 예를 들어 쿠키의 경우,
document.cookie에 JavaScript 접근을 통해 일부는 삭제할 수 있지만, HttpOnly 쿠키는 HTTP 응답의 여러
Set-Cookie 헤더를 통해서만 삭제 가능합니다. 이를 위해서는 호스트에 설정된 모든 쿠키를 완전히 파악해야 하고, 이는 복잡할 수 있습니다. 캐시는 더
어렵습니다. 브라우저의 네트워크 캐시를 제어할 수 있는 명령형 인터페이스는 아예 존재하지 않습니다.
이 문서는 이러한 로컬 저장소 및 기타 유형의 데이터 삭제를 새로운 방식으로 처리하는 메커니즘을 정의하고, 웹 개발자가 Clear-Site-Data HTTP 응답 헤더를 통해 사용자의 로컬 데이터 캐시를 지울 수 있는 기능을 제공합니다.
1.1. 예시
1.1.1. 로그아웃
https://supersecretsocialnetwork.example.com/logout에 Super Secret Social Network에서 로그아웃하고,
사이트 제작자는 로컬에 저장된 데이터가 결과적으로 삭제되길 원합니다.
응답에서 다음 HTTP 헤더를 전송함으로써 이를 달성할 수 있습니다:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
1.1.2. 특정 데이터만 삭제
https://megacorp.example.com/logout에 Megacorp Inc. 사이트에서 로그아웃합니다. Megacorp는 많은 서브도메인 서비스를
보유하고 있어, 로그아웃 시 어떤 데이터를 삭제해야 안전한지 명확하지 않습니다.
한 가지 옵션은 모든 것을 삭제하는 것이지만, 이로 인한 부작용이 있습니다.
하지만 Megacorp의 CEO는 "Irate Ibexes"에서 실수로 데이터가 삭제되어 오랜 진행상황을 잃은 경험으로 인해 이런 포괄적 삭제를 허용하지 않습니다.
하지만 개발자들은 "Minus"라는 애플리케이션은 안전하게 삭제해도 된다는 사실을 알고 있습니다. 그래서 로그아웃 랜딩 페이지에서 해당 서브도메인으로 요청을 보내는 방식으로 삭제를 지정할 수 있습니다(이상적으로 CORS 허용 및 CSRF 보호 POST로):
fetch("https://minus.megacorp.example.com/clear-site-data",
{
method: "POST",
mode: "cors",
headers: new Headers({
"CSRF": "[insert sekrit token here]"
})
});
해당 엔드포인트는 프리플라이트 요청에 올바른 CORS 헤더를, 실제 요청에는 아래와 같은 헤더를 반환할 것입니다:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
1.1.3. 중요 쿠키 유지
https://ads-are-awesome.example.com/optout에서 관심 기반 광고 수신을 거부(opt-out)합니다. 사이트 작성자는 추적 정보가
포함될 수 있는 DOM 접근 가능 데이터를 삭제하길 원하지만, 동시에 사용자가 방금 받은 opt-out 쿠키는 삭제되지 않도록 해야 합니다.
아래와 같이 "cookies"를 제외한 모든 타입을 포함하는 HTTP 헤더를 전송해 목적을 달성할 수 있습니다:
Clear-Site-Data: "cache", "storage", "executionContexts"
1.1.4. 킬 스위치
로컬의 데이터 원본을 모두 삭제하는 다음 헤더를 응답에 포함해 클라이언트 측 XSS의 지속 위험을 줄일 수 있습니다:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
Note: 서비스 워커를 설치하면 약 24시간마다 서버로 요청이 전송됩니다. 이런 재갱신 ping을 재난 상황에서 이런 헤더를 전송하는 데 사용할 수 있습니다. [SERVICE-WORKERS]
1.2. 목표
일반적으로 이 기능의 목적은 웹 개발자가 자사의 오리진에 대해 사용자 에이전트가 로컬에 저장하는 데이터를 더 잘 제어할 수 있도록 하는 것입니다. 특히 개발자는 다음을 신뢰성 있게 보장할 수 있어야 합니다:
-
오리진의 클라이언트 측 저장 메커니즘(예: [INDEXEDDB], WebSQL, 파일 시스템,
localStorage,sessionStorage)에 저장된 데이터가 삭제됨. -
오리진의 호스트에 대한 쿠키가 삭제됨 [RFC6265].
-
오리진에서 동작 중인 Web Worker(전용, 공유)가 종료됨.
-
오리진에 등록된 Service Worker가 종료 및 등록 해제됨.
-
오리진의 리소스가 사용자 에이전트의 로컬 캐시에서 삭제됨.
-
위 동작 전체가 HTTPS 오리진의 HTTP 버전에도 전파 가능함.
-
악의적 문서가 흥미로운 데이터를 메모리에 유지하고, 삭제될 경우 복원함으로써 위 동작을 우회할 수 없음.
2. 인프라
이 문서는 구문 명세에 ABNF 문법을 사용하며, [RFC5234] 및 [RFC7405]에 정의된 내용과, [RFC7230] 7항 및 동 문서 3.2.6항에 정의된 #rule,
quoted-string 규칙을 따릅니다.
이 문서는 알고리즘과 본문에서 사용하는 많은 기본 개념에 대해 Infra Standard를 참조합니다 [INFRA].
3. 사이트 데이터 삭제
개발자는 Clear-Site-Data HTTP 응답 헤더를 요청에 대한 응답으로 전달하여, 사용자 에이전트에게 다양한 유형의 관련 데이터를 삭제하도록 지시할 수
있습니다.
3.1. Clear-Site-Data HTTP 응답 헤더 필드
Clear-Site-Data HTTP 응답 헤더 필드는 특정 유형의 모든 데이터를
제거해야 함을 사용자 에이전트에 알립니다. 이 헤더는 다음과 같은 문법으로 표현됩니다.
Clear-Site-Data = 1#( quoted-string ) ; #rule는 RFC 7230의 Section 7에서 정의됨.
§3.2 페치 통합 및 §4.1 파싱에서는 Clear-Site-Data 헤더가 어떻게 처리되는지 설명합니다.
이 문서에서는 이 메커니즘을 사용하여 삭제할 수 있는 데이터 유형의 초기 집합을 정의합니다. 아래 설명을 참고하십시오. 미래 버전의 헤더는 추가 데이터 타입을 지원할 수 있으며, 이는 반드시 quoted-string 문법을 따라야 합니다. 사용자 에이전트는 미지의 유형을 파싱할 때 무시해야 합니다.
- "
cache" -
"
cache" 유형은 서버가 특정 origin에 연관된 response의 url에 연결된 로컬 캐시 데이터를 제거하고자 함을 나타냅니다. 여기에는 network cache 뿐만 아니라 프리렌더 페이지, 스크립트 캐시, 셰이더 캐시 등 사용자 에이전트가 구현하는 다양한 캐시의 데이터도 포함됩니다.구현 세부사항은 §4.2.3 오리진의 캐시 삭제에 있습니다.
https://example.com/clear에서 응답과 함께 전송될 때, 다음 헤더는https://example.com오리진에 연결된 캐시를 삭제합니다:Clear-Site-Data: "cache"
참고: 캐시는 일반적으로 오리진이 아니라 URL과 타임스탬프로 구성됩니다. 따라서 실제로 오리진별 캐시 삭제는 선형 스캔을 통해 구현할 수 있으며, 캐시가 클 경우 매우 비용이 많이 드는 작업이 될 수 있습니다.
- "
cookies" -
"
cookies" 유형은 서버가 특정 origin에 연관된 response의 url에 관련된 쿠키를 제거하고자 함을 의미합니다. 쿠키와 함께, HTTP 인증 정보[RFC7235] 및 Channel ID [CHANNELID]와 Token Binding [TOKBIND]에서 정의하는 오리진 바운드 토큰도 함께 삭제됩니다.구현 세부사항은 §4.2.4 오리진의 쿠키 삭제에 있습니다.
https://example.com/clear에서 응답과 함께 전송될 때, 다음 헤더는https://example.com오리진뿐 아니라 동일 등록 도메인의 모든 오리진(e.g.https://www.example.com/및https://more.subdomains.example.com/)에 연결된 쿠키를 삭제합니다.Clear-Site-Data: "cookies"
- "
storage" -
"
storage" 유형은 서버가 특정 origin에 연관된 response의 url에 위치한 로컬 저장 데이터를 제거하고자 함을 의미합니다. 여기에는 (localStorage,sessionStorage, [INDEXEDDB], [WEBDATABASE] 등과 같은 저장 메커니즘뿐 아니라, 서비스 워커 등록과 같은 간접적으로 관련된 메커니즘도 포함됩니다.구현 세부사항은 §4.2.5 오리진에 대한 DOM 접근 가능한 저장소 삭제에 있습니다.
https://example.com/clear에서 응답과 함께 전송될 때, 다음 헤더는https://example.com오리진의 DOM 접근 가능한 저장소를 삭제합니다:Clear-Site-Data: "storage"
- "
executionContexts" -
"
executionContexts" 유형은 서버가 특정 origin에 연관된 response의 url을 렌더링 중인 실행 컨텍스트를 무효화하고 리로드하고자 함을 의미합니다.https://example.com/clear에서 응답과 함께 전송될 때, 다음 헤더는https://example.com오리진을 표시 중인 실행 컨텍스트를 무효화하고 리로드합니다:Clear-Site-Data: "executionContexts"
- "
*" -
"
*"(와일드카드) 의사유형은 모든 유형을 지정한 것과 동일한 효과가 있음을 나타냅니다.https://example.com/clear에서 응답과 함께 전송될 때, 다음 헤더는https://example.com오리진에 연관된 모든 쿠키, 캐시, DOM 접근 가능한 저장소를 삭제하고, 동일 오리진의 실행 컨텍스트를 무효화 및 리로드합니다:Clear-Site-Data: "*"
참고: 와일드카드는 향후 이 헤더의 버전에서 더 많은 데이터 유형이 추가되더라도 모두 포함되도록 전방 호환성을 갖습니다.
전체 정리를 수행하려는 의도(예: 헤더가 아는 모든 오리진 데이터를 삭제)라면 반드시 와일드카드를 사용하세요.
위의 네 가지 유형의 축약형으로 와일드카드를 사용하지 마세요. 이 의미는 변경될 수 있습니다.
참고: 이곳에 정의된 문법은 향후 이 문서의 확장(더 세밀한 필터링 메커니즘 등)에 호환되도록 설계되었습니다. 예를
들어, "cookies"는 특정 쿠키 값을 제외하는 메커니즘이 필요할 수 있습니다. 모든 타입
이름을 큰따옴표로 감싸는 것은 간단한 쉼표 분할 방식에서 추후 JSON 처리 등으로 쉽게 확장할 수 있게 하여 하위 호환성을 보장합니다.
3.2. 페치 통합
Clear-Site-Data 헤더가 네트워크에서 받은 HTTP response에 존재한다면, 응답을 사용자에게 렌더링하기 전에 데이터를 반드시 삭제해야 합니다. 즉, 현재 HTTP-network fetch 알고리즘의 14단계 이후에 다음 단계를 실행합니다:
-
credentials flag가 설정되고, response의 header list에
Clear-Site-Data가 포함되어 있다면, §4.2 응답에 대한 데이터 삭제를 response에 대해 실행합니다.
참고: 이는 Set-Cookie 헤더 처리가 끝난 후에 발생합니다. 쿠키를
삭제하면 모두 삭제합니다. 이는 특정 쿠키만 삭제할 경우 애플리케이션이 불확정적이거나 보안상 취약해질 수 있기 때문입니다. 특정 쿠키만 삭제하려면
Set-Cookie 헤더 만료를 이용해야 합니다.
참고: fetch credentials flag는 쿠키 수정 제한을 의도하지만, Clear-Site-Data는 일관성을 위해 모든 타입에 동일
제약을 적용합니다.
4. 알고리즘
4.1. 파싱
response가 주어졌을 때, 사용자 에이전트는 response의
Clear-Site-Data 헤더 파싱을 다음과 같이 수행하여 타입 리스트를 반환할 수 있습니다:
-
types를 빈 리스트로 한다.
-
header를 extracting header list values 결과로 한다. 입력은
Clear-Site-Data, response의 header list. -
header가
null또는 실패라면 빈 리스트를 반환한다. -
header의 각 type에 대해, 첫 번째로 일치하는 문장 실행(스위치):
- `
"cache"` -
cache를 types에 추가.
- `
"cookies"` -
cookies를 types에 추가.
- `
"storage"` -
storage를 types에 추가.
- `
"executionContexts"` -
executionContexts를 types에 추가.
- `
"*"` -
cache, cookies, storage, executionContexts를 types에 모두 추가.
- `
-
types를 반환.
참고: 기존 값들은 위와 같이 단순한 스위치로 처리할 수 있습니다. 더 복잡한 타입 정의가 생기면, 파서는 전적으로 JSON 방식으로 전환될 수 있습니다.
4.2. response의 데이터 삭제
response(response)가 주어졌을 때, 사용자 에이전트는 response에 대한 사이트 데이터 삭제를 다음과 같이 수행할 수 있습니다:
-
response의 url이 a priori 인증된 URL이 아니라면, break한다.
-
types를 파싱한 response의
Clear-Site-Data헤더 결과로 한다. -
browsing contexts를 해당 origin과 types에 대한 데이터 삭제 준비 결과로 한다.
-
types의 각 type에 대해:
-
첫 번째 일치 문장 실행(스위치):
-
-
types에 "executionContexts"가 포함되어 있다면, browsing contexts를 리로드한다.
참고: 사용자 에이전트는 웹 개발자가 삭제 작업을 디버깅할 수 있도록, (성공시) 콘솔 메시지 또는 타임라인 항목 등의 메커니즘을 제공하는 것이 권장됩니다.
4.2.1. origin의 데이터 삭제 준비
origin(origin)과 타입 리스트(types)가 주어졌을 때, 사용자 에이전트는 origin의 데이터 삭제 준비를 다음 단계로 수행합니다. 이 알고리즘은, 인-메모리 JavaScript 변수로부터 삭제된 데이터를 복구하는 것을 방지하기 위해 샌드박싱된 브라우징 컨텍스트 리스트를 반환합니다.
-
sandboxed를 빈 리스트로 한다.
-
types에 "
executionContexts"가 없다면 sandboxed를 반환한다. -
각 context(사용자 에이전트의 브라우징 컨텍스트 집합 내)에 대해:
-
document를 context의 활성 문서로 한다.
-
document의 relevant settings object의 origin이 origin이 아니라면, continue.
-
빈 문자열을 입력값으로 하여 샌드박싱 지시문 파싱을 하고, document의 active sandboxing flag set에 출력한다.
-
-
sandboxed를 반환한다.
4.2.2. browsing contexts 다시 불러오기
browsing contexts (contexts) 리스트가 주어졌을 때, 사용자 에이전트는 다음과 같이 browsing contexts를 다시 불러오기를 실행할 수 있습니다:
-
contexts의 각 context에 대하여:
-
context의 active document의 relevant settings object의 global object의
Location객체의reload()를 실행한다.이 방법이 가장 단순하지만, 아마도 문서 안쪽까지 너무 깊게 관여하는 것일 수 있다. HTML에서 관련 부분을 복사하여 작성하는 편이 낫겠음.
-
4.2.3. origin의 캐시 삭제
origin (origin)이 주어졌을 때, 사용자 에이전트는 다음과 같이 origin의 캐시 삭제를 실행할 수 있습니다:
-
host를 origin의 host로 설정한다.
-
cache list를 network cache에서
target URI의 host가 host와 동일한 엔트리의 집합으로 한다. -
cache list의 각 entry에 대하여:
-
entry를 network cache에서 제거한다.
-
-
사용자 에이전트가 순수 network cache 이외의 캐시를 구현했다면, 반드시 origin에 일치하는 해당 캐시의 모든 엔트리도 제거해야 한다.
여기서는 [RFC7234]에 정의된 network cache에만 다루지만, 실제로는 사용자 에이전트가 캐시하는 모든 것은 아니다. 벤더별 섹션에서 어느 정도 추상적으로 기술할 수 있을까? 예를 들어, Chrome은 프리렌더 페이지, 스크립트 캐시, WebGL 셰이더 캐시, WebRTC 조각, 주소 창 제안 캐시 등 다양한 네트워크 외 캐시도 모두 삭제한다. 아마도 [STORAGE]에서 더 명확해질 수 있음.
4.2.4. origin의 쿠키 삭제
origin (origin)이 주어졌을 때, 사용자 에이전트는 다음과 같이 origin의 쿠키 삭제를 실행할 수 있습니다:
참고: 전체 등록 도메인의 모든 쿠키를 삭제합니다. 쿠키는 same-origin 정책을 무시하므로,
특정 서브도메인만 쿠키를 삭제하는 경우 애플리케이션이 비정의 상태에 놓일 수 있습니다. 예를 들어, accounts.google.com과
mail.google.com은 모두 사용자의 로그인 상태를 나타내는 쿠키를 가짐.
참고: 이 알고리즘은 사용자 에이전트가 cookie store를 구현한다고 가정합니다([RFC6265] 5.3절 참고). 이를 통해 호스트별 쿠키 리스트를 얻고 개별 쿠키를 삭제할 수 있습니다.
-
cookie list를 cookie store에서
domain속성이 registered와 domain-match인 쿠키들의 집합으로 한다. -
cookie list의 각 cookie에 대하여:
-
cookie를 cookie store에서 삭제한다.
-
-
사용자 에이전트가 쿠키 유사 저장소를 추가로 지원하는 경우, 반드시 origin의 host가 등록 도메인이 registered인 경우 모두 삭제해야 함.
참고: 예) 사용자 에이전트가 Flash를 지원하면, local stored object는 NPP_ClearSiteData로 삭제됨.
-
[CHANNELID] 및 [TOKBIND]의 바운드 토큰, Channel ID도 origin의 등록 도메인 registered에 대해 삭제해야 함.
-
authentication entry와 proxy-authentication entry도 origin의 등록 도메인 registered에 대해 삭제해야 함.
토큰/ID와 HTTP 인증 삭제 과정이 설명이 불충분함. <https://github.com/w3c/webappsec-clear-site-data/issues/2>
4.2.5. origin의 DOM 접근 가능한 저장소 삭제
origin (origin)이 주어졌을 때, 사용자 에이전트는 다음과 같이 origin의 DOM 접근 가능한 저장소 삭제를 수행할 수 있습니다:
-
사용자 에이전트의 local storage areas 집합의 각 area에 대하여 [HTML]:
-
사용자 에이전트의 session storage areas 집합의 각 area에 대하여 [HTML]:
-
databases 집합 중 origin에 해당하는 각 database에 대하여 [INDEXEDDB]:
-
사용자 에이전트의 service worker registrations 집합의 각 registration에 대해:
-
registration의 scope URL origin이 origin이면:
-
registration에
unregister()를 실행한다.
-
-
-
사용자 에이전트의 application caches 집합의 각 appcache에 대해:
-
appcache의 application cache group이 origin이 origin인 URL로 식별되면:
-
appcache를 폐기한다.
-
-
-
다른 script 접근 가능 저장소 메커니즘에 대해서도, 사용자 에이전트는 반드시 해당 origin에 연관된 모든 데이터를 삭제해야 한다. 이는 다음을 포함(한정되지 않음):
-
origin의 WebSQL 데이터베이스 [WEBDATABASE]
-
origin의 파일시스템 [file-system-api]
-
플러그인 데이터(예: Flash는 NPP_ClearSiteData를 통해)
-
5. 보안 고려 사항
5.1. 완전하지 않은 삭제
저장소 유형 하나만 삭제하면 애플리케이션이 불확정 상태가 될 수 있습니다. 이를 방지하고자, 모든 저장소를 블록 단위로 삭제하고, 헤더는 반드시 보안 연결을 통해 전달하도록 요구합니다.
5.2. Service workers
Clear-Site-Data 헤더는 반드시 네트워크에서 가져온 응답에만 적용되어야 하며, service worker가 제공하는 응답에는 적용하지 않아야 합니다.
Service worker는 자신의 범위 내에서 third-party 요청을 포함해, 임의의 응답을 반환할 수 있기 때문입니다. Clear-Site-Data를 지원하면, 이들은 임의의 오리진의 데이터를 삭제할 수 있는 권한을 얻게 됩니다.
요청이 service worker로 전송되었지만 처리되지 않고, service-workers mode가 "none"인 상태로
다시 네트워크에 요청된다면, 그 응답은 네트워크 응답으로 간주하며 처리할 수 있습니다. service worker에서 응답을 얻으려던 시도는 무관합니다.
또한 service worker의 업데이트는 네트워크 응답이므로 이 제한의 영향을 받지 않습니다. 이는 §1.1.4 Kill Switch의 사용 사례를 지원하는 데 중요합니다.
6. 프라이버시 고려 사항
6.1. 웹 개발자가 타이밍을 제어
적절한 시점에 트리거된다면, Clear-Site-Data는 사용자의 에이전트에서
민감한 데이터를 삭제하여 프라이버시와 보안을 높여줄 수 있습니다. 하지만, 삭제 이벤트의 트리거는 웹 개발자가 제어하며(사용자가 아님), 악의적이지 않은 사이트라 하더라도
사용자는 삭제 시점이나 삭제되는 데이터 유형을 제어할 수 없습니다.
특정 시점에 실제로 사이트 데이터가 삭제되었는지 확실히 보장하려면, 사용자는 사용자 에이전트의 데이터 삭제 기능을 사용해야 합니다.
최소한, 사용자 에이전트는 웹 개발자에 제공하는 기능을 동일하게 사용자에게도 제공해야 합니다([RFC6919] 의미의 OUGHT TO). 플랫폼 수준에서 제공하지 못하는 기능(예: 방문 기록 삭제 등)까지 더 많이 제공하는 것이 이상적입니다.
6.2. 디스크에 남은 데이터 자국
Clear-Site-Data가 사용자 에이전트에서
삭제 이벤트를 트리거하지만, 삭제 이후 사용자의 디스크에 대한 상태를 보장하기는 어렵습니다. 특히, 사이트의 모든 데이터 흔적을 디스크에서 완전히 삭제하는 것은 사용자
에이전트에게 맡겨지며, 이는 현실적으로 거의 불가능한 문제입니다(예로 가상 메모리 등).
즉, 대부분의 사용자 에이전트는 데이터 삭제를 "최대한" 구현하지만, 완전한 삭제를 보장하지 못합니다.
디스크에 사이트 데이터가 절대로 남지 않게 하려면, 데이터를 디스크에 의도적으로 기록하지 않기로 약속된 브라우징 모드(예: Chrome의 "Incognito", IE의 "InPrivate" 등)를 사용하는 것이 최선입니다. 이러한 모드는 실제로 데이터를 디스크에 남기지 않도록 더 잘 동작하나, 완전한 제거는 근본적 한계에 여전히 직면할 수 있습니다.
7. IANA 고려사항
영구 메시지 헤더 필드 레지스트리는 다음 등록 정보로 업데이트되어야 합니다: [RFC3864]
7.1. Clear-Site-Data
- Header 필드 이름
- Clear-Site-Data
- 적용 프로토콜
- http
- 상태
- standard
- 작성자/변경 관리
- W3C
- 명세 문서
- 이 명세(See §3.1 The Clear-Site-Data HTTP Response Header Field)
8. 감사의 말
Michal Zalewski는 이 개념의 변형을 제안했으며, Mark Knichel은 세부사항 정교화에 도움을 주었습니다.