Engineering note · Browser

자바스크립트로 조작할 수 없는 Forbidden Header와 HttpOnly 쿠키

2026년 07월 22일이현수
태그browserhtmlsecurity

브라우저 자바스크립트에서 HTTP 헤더와 HttpOnly 쿠키 조작이 차단되는 이유, 보안 메커니즘, 확장 프로그램 API 등 현실적인 해결 대안을 정리한다.

내가 제공하는 사이트에서 다른 사이트를 크롤링하거나 API 요청하려고 할 때 HostReferer 같은 헤더 값이나, WMONID, JSESSIONID 같은 세션 쿠키를 가져오고싶을 때가 있다. 하지만 보안상 이유로 브라우저 엔진 차원에서 완전히 차단된다.

Forbidden Header Name

ts
// 브라우저 자바스크립트 환경
fetch('https://api.example.com/data', {
  headers: {
    'Host': 'target.com',
    'Referer': 'https://trusted-site.com',
    'Cookie': 'JSESSIONID=abcdef123456',
  },
})

fetch()XMLHttpRequest 에서 헤더를 임의로 지정해도 브라우저는 적용하지 않는다. 브라우저가 커널 레벨에서 요청을 조합할 때 이런 헤더들은 원래 페이지의 진짜 값으로 덮어쓴다. 이렇게 수정을 금지한 HTTP 요청 헤더들을 Forbidden Header Name 이라 한다.

  • Accept-Charset, Accept-Encoding
  • Connection, Keep-Alive
  • Content-Length, Transfer-Encoding
  • Cookie
  • Date, Host, Origin, Referer
  • Sec- 로 시작하는 모든 헤더
  • Proxy- 로 시작하는 모든 헤더

이는 웹 보안과 HTTP 통신 무결성을 유지하기 위한 보호 장치다. 중요 헤더를 자유롭게 바꿀 수 있게 되면, CSRF 공격이나 CORS 정책이 무의미해진다. 서버는 요청 헤더의 출처 정보를 신뢰하고 권한을 검증하는데, 클라이언트 스크립트가 변경하면 출처 기반 방어가 무력화된다.

Cookie 역시 Forbidden Header Name 이어서 조작이 불가능한데, 서버가 HttpOnly 플래그를 설정하면, document.cookie 를 통해서도 해당 쿠키를 읽거나 쓸 수 없게 된다.

ts
// HttpOnly 플래그가 설정된 JSESSIONID, WMONID 등은 출력되지 않는다
console.log(document.cookie)

이 제약은 XSS가 성공하더라도 사용자의 세션 토큰을 외부 서버로 전송하지 못하도록 차단하는 보안 설계다.

브라우저 확장 프로그램

브라우저 확장 프로그램은 더 높은 권한을 가진다. manifest.jsoncookies 권한과 해당 도메인의 host_permissions를 선언하면, 확장 프로그램의 백그라운드 서비스 워커에서 chrome.cookies API로 HttpOnly 쿠키 값을 읽을 수 있다.

json
// manifest.json
{
  "permissions": ["cookies"],
  "host_permissions": ["https://*.example.com/*"]
}
ts
// 확장 프로그램 서비스 워커
chrome.cookies.get({ url: 'https://example.com', name: 'JSESSIONID' }, (cookie) => {
  if (cookie) {
    console.log('HttpOnly 쿠키 값:', cookie.value)
  }
})

브라우저 밖 런타임 사용

Node, Python, Go 등의 런타임 환경은 브라우저 제약이 없으니 패킷을 마음대로 구성할 수 있다. 크롤링이나 자동화 작업에서는 브라우저 밖 런타임을 사용하는 것이 훨씬 수월하다.