コアコンセプト
HttpOnly vs クライアントサイドストレージ
HttpOnly とマークされた Cookie は、クライアントサイド JavaScript(cookieStore または document.cookie)からアクセスまたは変更することはできません。ただし、ブラウザはアクティブな HttpOnly Cookie を発信 HTTP リクエストヘッダー(Cookie)に自動的に付加します。
- 現在の
HttpOnly値を検査するには:get_network_requestを介して、発信 HTTP リクエストのCookieリクエストヘッダーを確認します。 - Cookie がどのように作成または構成されたかを検査するには: ログイン/認証レスポンスの
Set-Cookieレスポンスヘッダーを確認します。 - 非
HttpOnlyCookie を検査するには: モダンなcookieStoreAPI を使用してevaluate_scriptを実行します(async () => await cookieStore.getAll())。
セッション戦略: ライブタブ vs 分離コンテキスト
状態の汚染(例: 残余の分析情報や認証トークン)を避けるために、適切なセッション環境を選択してください:
| 戦略 | 使用するタイミング | セットアップ / ティアダウン |
|---|---|---|
| ライブタブ(アクティブページ) | アクティブなユーザーセッション、ライブの 401/403 エラー、または現在の状態を診断する場合。 | 現在選択されているページで直接操作します。 |
クリーンスレート(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: ...) を使用 |
[!WARNING] JavaScript で
HttpOnlyCookie をクリアしようとすると(cookieStore.deleteまたはdocument.cookie = "...; max-age=0")、サイレントに失敗します。認証なし状態または新しい状態でテストするには、isolatedContextを指定したnew_pageを使用して、必ず新しい分離コンテキストを起動してください。
ワークフローパターン
1. 認証失敗とリダイレクトの診断(401 / 403)
認証が必要なページリクエストが失敗し、401/403 を返したり、ログインページにリダイレクトされる場合:
- 最近のリクエストを一覧表示:
list_network_requestsをincludePreservedRequests: trueで呼び出します。 - 対象のリクエストを見つける: 失敗したリクエスト(401/403)またはリダイレクト(302/307)を特定します。
- 送信
Cookieヘッダーを検査:reqidを指定してget_network_requestを呼び出します。Cookieヘッダーが添付されているか、必要なトークン(例:SESSION_ID,auth_token)が送信されているかを確認します。
- アクティブ検査をトリガー(最近のリクエストがない場合):
- Cookie が以前のセッションで設定され、ネットワーク呼び出しがリストされていない場合、リクエストをトリガーします:
navigate_pageをreload: trueで使用する、またはevaluate_scriptを() => fetch(window.location.href)で呼び出します。
- 次に、新しいリクエストに対して
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=StrictCookie はクロスサイトナビゲーションでは省略されます。 - 有効期限:
ExpiresまたはMax-Ageが経過していないか確認します。
- Path の不一致: 例:
- 以前のログイン/ハンドシェイクレスポンスの
2. Cookie バナーと同意コンフォーマンステスト
同意前または拒否時に、非必須またはトラッキング Cookie が設定されていないことを確認するには:
- クリーンに開始: 専用の名前を持つ新しい分離コンテキストを開きます:
{"url": "<PAGE_URL>", "isolatedContext": "consent-test-1"} - ベースライン Cookie を記録: バナーと対話する前に、
evaluate_scriptをasync () => await cookieStore.getAll()で実行します。 - 早期のネットワークリクエストと問題を検査:
list_network_requestsを呼び出して、同意前にサードパーティのトラッキングビーコンが発火していないことを確認します。list_console_messagesをtypes: ["issue"]で呼び出し、トラッキング警告がないか確認します。
- 同意バナーと対話:
take_snapshotでスナップショットを取得し、「拒否」または「すべて拒否」ボタンのuidを見つけます。clickでボタンをクリックします。
- Cookie の差分を検証:
- クリック後に
evaluate_scriptをasync () => await cookieStore.getAll()で実行し、厳密に必要な Cookie または同意状態の Cookie のみが存在することを確認します。
- クリック後に
- 同意撤回のテスト(ライフサイクル監査):
- 同意の撤回や設定変更を監査する場合:
- 「Cookie 設定」「環境設定の管理」、またはフッターのプライバシートリガーを見つけてクリックします(
take_snapshot→click)。 - 非必須カテゴリの選択を解除するか、「すべて撤回」/「環境設定を保存」をクリックします。
cookieStore.getAll()を再度実行して、以前に受け入れられた非必須 Cookie が消去または期限切れになったことを確認します。- 後続のアクションで
list_network_requestsを呼び出し、トラッキングビーコンが発火しなくなったことを確認します。
- 「Cookie 設定」「環境設定の管理」、またはフッターのプライバシートリガーを見つけてクリックします(
- 同意の撤回や設定変更を監査する場合:
- コンテキストのティアダウン: 監査が完了したら
close_pageを呼び出し、残った Cookie が後続のタスクに影響しないようにします。
3. Cookie セキュリティ、SameSite、および CHIPS(Partitioned Cookie)の監査
- 迅速な方法: ネイティブ DevTools 問題(推奨):
list_console_messagesを次のパラメータで呼び出します:{ "types": ["issue"], "includePreservedMessages": true }CookieIssueエントリがないか確認します。例えば:SameSiteNoneInsecure:SecureなしでSameSite=None。ThirdPartyCookiePhaseout: サードパーティ Cookie がブロックまたは制限されている。SchemefulSameSite: クロススキームの Cookie 問題。PartitionedCookies: 無効な CHIPS パーティショニング属性。
- 詳細監査: Lighthouse サードパーティ Cookie:
lighthouse_auditをmode: "navigation"およびoutputDirPath: "/tmp/lh-report"で実行します。- フルレポートをコンテキストに読み込まずに、特定の Cookie 監査を抽出します:
node -e "const r=require('/tmp/lh-report/report.json'); const a=r.audits['third-party-cookies']; console.log(JSON.stringify({score: a?.score, display