cookie-debugging について
Chrome DevTools MCP ツールでブラウザーの Cookie を調べ、認証や同意状態を診断するスキルです。HttpOnly Cookie と JavaScript から扱える Cookie を区別し、分離コンテキストでのテスト手順を示します。
主な機能
- 01リクエストとレスポンスの Cookie ヘッダー確認
- 02クライアント側 Cookie の読み取り
- 03分離したブラウザーコンテキストでのテスト
- 04認証失敗の追跡
- 05同意状態と Cookie セキュリティの監査
活用シーン
- 01401 または 403 応答の調査
- 02Cookie 同意動作の検証
- 03Cookie 属性やブラウザー問題の確認
- 04未認証セッションのテスト
MCP 対応
`list_network_requests`、`get_network_request`、`evaluate_script`、`new_page` などの Chrome DevTools MCP ツールで Cookie を調査・テストします。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ chromedevtools/ chrome-devtools-mcp --skill cookie-debuggingインストール後、Claude Code で/cookie-debuggingを入力して読み込まれたか確認します。
詳細
中核となる概念
ページのターゲティング: ページスコープのツール(list_network_requests、get_network_request、list_console_messages、evaluate_script、navigate_page、take_snapshot、click、lighthouse_audit、close_page など)には pageId パラメータが必要です。利用可能なページ ID は list_pages を使用するか、new_page から取得してください。
HttpOnly とクライアントサイドストレージ
HttpOnly が付与された Cookie は、クライアントサイド JavaScript(cookieStore または document.cookie)からアクセスしたり変更したりすることはできません。ただし、ブラウザはアクティブな HttpOnly Cookie を送信 HTTP リクエストヘッダー(Cookie)に自動的に付加します。
- 現在の
HttpOnlyの値を確認するには:get_network_requestを使用して、送信 HTTP リクエストのCookieリクエストヘッダーを確認します。 - Cookie がどのように作成または設定されたかを確認するには: ログイン/認証レスポンスの
Set-Cookieレスポンスヘッダーを確認します。 HttpOnlyでない Cookie を確認するには: モダンなcookieStoreAPI(async () => await cookieStore.getAll())を指定してevaluate_scriptを使用します。
セッション戦略: ライブタブと分離コンテキスト
状態の混入(残留したアナリティクスや認証トークンなど)を避けるため、適切なセッション環境を選択してください:
| 戦略 | 使用する場面 | セットアップ/ティアダウン |
|---|---|---|
| ライブタブ(アクティブページ) | アクティブなユーザーセッション、ライブの 401/403 エラー、現在の状態を診断する場合。 | ユーザーの既存ページを操作します。list_pages からその pageId を取得します。 |
クリーンスレート(isolatedContext) | Cookie 同意バナー、初回訪問、Cookie ゼロの保証をテストする場合。 | 一意の isolatedContext(例: "consent-audit-1")を指定して new_page を呼び出します。終了したら close_page を呼び出します。 |
クライアントサイドの機能と制限
| アクション | クライアント JavaScript(cookieStore / document.cookie) | DevTools ネットワーク&コンテキストツール |
|---|---|---|
| 非 HttpOnly の読み取り | ✅ async () => await cookieStore.getAll() | ✅ get_network_request(リクエストの Cookie) |
| HttpOnly の読み取り | ❌ ブラウザのセキュリティによりブロック | ✅ get_network_request(リクエストの Cookie) |
属性の検査(Domain、Path、SameSite、Expires) | ✅ async () => await cookieStore.getAll() | ✅ get_network_request(レスポンスの Set-Cookie) |
| 非 HttpOnly の変更/削除 | ✅ async () => await cookieStore.set(...) | N/A |
| HttpOnly の変更/削除 | ❌ JavaScript ではサイレントに失敗 | ✅ クリーンな状態にするには new_page(isolatedContext: ...) を使用 |
警告
JavaScript(
cookieStore.deleteまたはdocument.cookie = "...; max-age=0")でHttpOnlyCookie を削除しようとすると、サイレントに失敗します。未認証またはフレッシュな状態でテストするには、常にisolatedContextを指定したnew_pageを使用して新しい分離コンテキストを生成してください。
ワークフローパターン
1. 認証の失敗とリダイレクトの診断 (401 / 403)
認証済みページのリクエストが失敗したり、401/403 を返したり、ログインにリダイレクトされたりする場合:
- 最近のリクエストを一覧表示:
includePreservedRequests: trueを指定してlist_network_requestsを呼び出します。 - 対象のリクエストを特定: 失敗しているリクエスト (401/403) またはリダイレクト (302/307) を探します。
- 送信された
Cookieヘッダーを検査:reqidを指定してget_network_requestを呼び出します。Cookieヘッダーが付与されていたか、必要なトークン (例:SESSION_ID、auth_token) が送信されていたかを確認します。
- アクティブな検査をトリガー (最近のリクエストが存在しない場合):
- 以前のセッションで Cookie が設定されており、ネットワーク呼び出しが一覧にない場合は、リクエストをトリガーします:
type: "reload"を指定してnavigate_pageを使用する、または() => fetch(window.location.href)を指定してevaluate_scriptを呼び出す
- その後、新しいリクエストに対して
get_network_requestを呼び出し、アクティブなCookieヘッダーを検査します。
- 以前のセッションで Cookie が設定されており、ネットワーク呼び出しが一覧にない場合は、リクエストをトリガーします:
- 設定リクエストを追跡: Cookie が欠落しているか拒否された場合:
- 以前のログイン/ハンドシェイクのレスポンスで
Set-Cookieディレクティブを確認します:- Path の不一致: 例えば、リクエスト先が
/であるのにPath=/apiになっている。 - Domain の不一致: 例えば、
Domain=api.example.comによりsub.example.comで Cookie が設定されない。 - HTTP での Secure フラグ:
SecureCookie は暗号化されていないhttp://経由では送信されません。 - SameSite によるブロック:
SameSite=Strictの Cookie はクロスサイトのナビゲーションでは省略されます。 - 有効期限:
ExpiresまたはMax-Ageが経過していないかを確認します。
- Path の不一致: 例えば、リクエスト先が
- 以前のログイン/ハンドシェイクのレスポンスで
2. Cookie バナーと同意の適合性テスト
同意前または拒否時に、不要な Cookie やトラッキング Cookie が設定されていないことを検証するには:
- クリーンな状態で開始: 専用の名前を付けた新しい分離コンテキストを開きます:
{"url": "<PAGE_URL>", "isolatedContext": "consent-test-1"} - ベースラインの Cookie を記録: バナーを操作する前に、
async () => await cookieStore.getAll()を指定してevaluate_scriptを実行します。 - 早期のネットワークリクエストと問題を検査:
list_network_requestsを呼び出し、同意前にサードパーティのトラッキングビーコンが発火していないことを確認します。types: ["issue"]を指定してlist_console_messagesを呼び出し、トラッキングに関する警告がないか確認します。
- 同意バナーを操作:
take_snapshotでスナップショットを取得し、「拒否」または「すべて拒否」ボタンのuidを特定します。clickでボタンをクリックします。
- Cookie の差分を検証:
- クリック後に
async () => await cookieStore.getAll()を指定してevaluate_scriptを実行し、厳密に必要な Cookie または同意状態の Cookie のみが存在することを確認します。
- クリック後に
- 同意の撤回をテスト (ライフサイクル監査):
- 同意の撤回や設定変更を監査する場合:
- 「Cookie 設定」、「設定を管理」、またはフッターのプライバシートリガーを特定してクリックします (
take_snapshot$\rightarrow$click)。 - 不要なカテゴリの選択を解除するか、「すべて撤回」/「設定を保存」をクリックします。
- 再度
cookieStore.getAll()をクエリし、以前に承諾された不要な Cookie が削除または失効していることを確認します。 - 後続のアクションに対して
list_network_requestsを呼び出し、トラッキングビーコンがこれ以上発火しないことを確認します。
- 「Cookie 設定」、「設定を管理」、またはフッターのプライバシートリガーを特定してクリックします (
- 同意の撤回や設定変更を監査する場合:
- コンテキストを破棄: 監査が完了したら
close_pageを呼び出し、残存する Cookie が後続のタスクに影響を与えないようにします。
3. Cookie のセキュリティ、SameSite、CHIPS(パーティション化 Cookie)の監査
- 最短手順:ネイティブ DevTools の問題(推奨):
list_console_messagesを次のように呼び出します。{ "pageId": 1, "types": ["issue"], "includePreservedMessages": true }- 次のような
CookieIssueエントリがないか確認します。SameSiteNoneInsecure:Secureを指定せずにSameSite=Noneを設定しています。ThirdPartyCookiePhaseout:サードパーティ Cookie がブロックまたは制限されています。SchemefulSameSite:スキームをまたぐ Cookie の問題です。PartitionedCookies:CHIPS のパーティショニング属性が無効です。
- 詳細監査:Lighthouse のサードパーティ Cookie 監査:
mode: "navigation"を指定してlighthouse_auditを実行します(デフォルトの一時ファイルを使用するにはoutputDirPathを省略するか、ワークスペース内のディレクトリを指定します)。- 返された
report.jsonのパスから、該当する Cookie 監査のみを抽出します。レポート全体をコンテキストに読み込む必要はありません。node -e "const r=require('<path/to/report.json>'); const a=r.audits['third-party-cookies']; console.log(JSON.stringify({score: a?.score, displayValue: a?.displayValue, items: a?.details?.items}))"
4. クライアント側での Cookie の確認と操作
クライアントからアクセスできる HttpOnly ではない Cookie(UI 設定や機密性のない機能フラグなど)を対象とします。
- Cookie と属性の読み取り:
- 最新の非同期 Cookie Store API を使用します。
async () => await cookieStore.getAll(); - セキュリティ保護されていない HTTP オリジンでの代替手段:
() => document.cookie
- 最新の非同期 Cookie Store API を使用します。
- Cookie の設定/変更:
cookieStoreを使用してクライアント Cookie を設定します。async () => await cookieStore.set({ name: 'theme', value: 'dark', expires: Date.now() + 86400000, sameSite: 'lax', });
- Cookie の削除:
- クライアント Cookie をクリアします。
async () => await cookieStore.delete('theme');
- クライアント Cookie をクリアします。
トラブルシューティング
cookieStoreが未定義:cookieStoreにはセキュアコンテキスト(https://、localhost、または127.0.0.1)が必要です。セキュリティ保護されていない HTTP オリジンでは、() => document.cookieを使用するか、HTTPS 経由でテストしてください。evaluate_scriptが空の結果を返す/Promise が未解決:cookieStoreのメソッドは非同期です。呼び出しは必ずasync () => await cookieStore.getAll()のようにラップしてください。- JavaScript から Cookie を確認できない:Cookie に
HttpOnlyが設定されています。ネットワークリクエストを実行してget_network_requestを呼び出し、Cookieリクエストヘッダーを確認してください。 - JavaScript で削除しても Cookie が残る:Cookie に
HttpOnlyが設定されているか、一致するPathとDomainパラメーターが必要です。新しいページで新しいisolatedContextを使用し、初期状態に戻してください。 - レスポンスで設定された Cookie がリクエストで送信されない:
- ページが
http://である一方、Cookie にSecureが指定されていないか確認します。 Domainによってサブドメインが制限されていないか確認します。- ブラウザーによる拒否理由を確認するため、
list_console_messages(types: ["issue"])を確認します。
- ページが
- 残存 Cookie が監査に影響する:コンプライアンステストの実行時は、必ず一意の
isolatedContextを指定してnew_pageを使用し、完了後にclose_pageを呼び出してください。