cookie-debugging
GitHub利用 Chrome DevTools MCP 调试 Cookie、会话状态及认证问题,涵盖 HttpOnly 检查、Session 策略选择及合规性审计。
Trigger Scenarios
Install
npx skills add ChromeDevTools/chrome-devtools-mcp --skill cookie-debugging -g -y
SKILL.md
Frontmatter
{
"name": "cookie-debugging",
"description": "Uses Chrome DevTools MCP for inspecting, debugging, and testing cookies, session state, authentication issues, and cookie consent compliance. Use when diagnosing 401\/403 errors, authentication redirects, session expiration, Cookie\/Set-Cookie header issues, cookie banner consent conformance, or third-party cookie\/SameSite\/Partitioned cookie warnings."
}
Core Concepts
HttpOnly vs Client-Side Storage
Cookies marked HttpOnly cannot be accessed or modified by client-side JavaScript (cookieStore or document.cookie). However, the browser automatically attaches active HttpOnly cookies to outgoing HTTP request headers (Cookie).
- To inspect current
HttpOnlyvalues: Look at theCookierequest header of any outgoing HTTP request viaget_network_request. - To inspect how cookies were created or configured: Look at the
Set-Cookieresponse header of login/auth responses. - To inspect non-
HttpOnlycookies: Useevaluate_scriptwith the moderncookieStoreAPI (async () => await cookieStore.getAll()).
Session Strategy: Live Tab vs Isolated Context
Choose the right session environment to avoid state contamination (e.g., residual analytics or auth tokens):
| Strategy | When to Use | Setup / Teardown |
|---|---|---|
| Live Tab (Active Page) | Diagnosing an active user session, live 401/403 error, or current state. | Operates directly on the currently selected page. |
Clean-Slate (isolatedContext) |
Testing cookie consent banners, first-time visits, or zero-cookie guarantees. | Call new_page with a unique isolatedContext (e.g. "consent-audit-1"). When finished, call close_page. |
Client-Side Capabilities & Limitations
| Action | Client JavaScript (cookieStore / document.cookie) |
DevTools Network & Context Tools |
|---|---|---|
| Read Non-HttpOnly | ✅ async () => await cookieStore.getAll() |
✅ get_network_request (Request Cookie) |
| Read HttpOnly | ❌ Blocked by browser security | ✅ get_network_request (Request Cookie) |
Inspect Attributes (Domain, Path, SameSite, Expires) |
✅ async () => await cookieStore.getAll() |
✅ get_network_request (Response Set-Cookie) |
| Modify / Delete Non-HttpOnly | ✅ async () => await cookieStore.set(...) |
N/A |
| Modify / Delete HttpOnly | ❌ Silent failure in JavaScript | ✅ Use new_page(isolatedContext: ...) for clean state |
[!WARNING] Attempting to clear an
HttpOnlycookie via JavaScript (cookieStore.deleteordocument.cookie = "...; max-age=0") will silently fail. To test in an unauthenticated or fresh state, always spawn a new isolated context usingnew_pagewithisolatedContext.
Workflow Patterns
1. Diagnosing Authentication Failures & Redirects (401 / 403)
When an authenticated page request fails, returns 401/403, or redirects to login:
- List Recent Requests: Call
list_network_requestswithincludePreservedRequests: true. - Find the Target Request: Locate the failing request (401/403) or redirect (302/307).
- Inspect Outgoing
CookieHeader: Callget_network_requestwith thereqid.- Verify if the
Cookieheader was attached and whether required tokens (e.g.SESSION_ID,auth_token) were sent.
- Verify if the
- Trigger Active Inspection (If no recent request exists):
- If the cookie was set in a previous session and no network call is listed, trigger a request:
- Use
navigate_pagewithreload: true, OR - Call
evaluate_scriptwith() => fetch(window.location.href)
- Use
- Then call
get_network_requeston the new request to inspect the activeCookieheader.
- If the cookie was set in a previous session and no network call is listed, trigger a request:
- Trace the Setting Request: If the cookie is missing or rejected:
- Check earlier login/handshake responses for
Set-Cookiedirectives:- Path mismatch: e.g.,
Path=/apiwhen the request is to/. - Domain mismatch: e.g.,
Domain=api.example.compreventing cookies onsub.example.com. - Secure flag on HTTP:
Securecookies are never sent over unencryptedhttp://. - SameSite blocking:
SameSite=Strictcookies are omitted on cross-site navigations. - Expiration: Check if
ExpiresorMax-Ageelapsed.
- Path mismatch: e.g.,
- Check earlier login/handshake responses for
2. Cookie Banner & Consent Conformance Testing
To verify that no non-essential or tracking cookies are set before consent or when declining:
- Start Clean: Open a fresh isolated context with a dedicated name:
{"url": "<PAGE_URL>", "isolatedContext": "consent-test-1"} - Record Baseline Cookies: Before interacting with the banner, run
evaluate_scriptwithasync () => await cookieStore.getAll(). - Inspect Premature Network Requests & Issues:
- Call
list_network_requeststo ensure no third-party tracking beacons fired before consent. - Call
list_console_messageswithtypes: ["issue"]to check for tracking warnings.
- Call
- Interact with Consent Banner:
- Capture snapshot with
take_snapshotto locate the "Decline" or "Reject All" buttonuid. - Click the button with
click.
- Capture snapshot with
- Verify Cookie Difference:
- Run
evaluate_scriptwithasync () => await cookieStore.getAll()after clicking to assert that only strictly necessary or consent-state cookies exist.
- Run
- Test Consent Revocation (Lifecycle Audit):
- When auditing consent withdrawal or preference changes:
- Locate and click the "Cookie Settings", "Manage Preferences", or footer privacy trigger (
take_snapshot$\rightarrow$click). - Deselect non-essential categories or click "Revoke All" / "Save Preferences".
- Re-query
cookieStore.getAll()to verify previously accepted non-essential cookies were cleared or expired. - Call
list_network_requestson subsequent actions to ensure tracking beacons are no longer fired.
- Locate and click the "Cookie Settings", "Manage Preferences", or footer privacy trigger (
- When auditing consent withdrawal or preference changes:
- Teardown Context: Call
close_pagewhen the audit is complete to prevent leftover cookies from affecting subsequent tasks.
3. Auditing Cookie Security, SameSite & CHIPS (Partitioned Cookies)
- Fast-Track: Native DevTools Issues (Recommended):
- Call
list_console_messageswith:{ "types": ["issue"], "includePreservedMessages": true } - Check for
CookieIssueentries, such as:SameSiteNoneInsecure:SameSite=NonewithoutSecure.ThirdPartyCookiePhaseout: Third-party cookie blocked or restricted.SchemefulSameSite: Cross-scheme cookie issues.PartitionedCookies: Invalid CHIPS partitioning attributes.
- Call
- Deep Audit: Lighthouse Third-Party Cookies:
- Run
lighthouse_auditwithmode: "navigation"andoutputDirPath: "/tmp/lh-report". - Extract the specific cookie audit without loading the full report into context:
node -e "const r=require('/tmp/lh-report/report.json'); const a=r.audits['third-party-cookies']; console.log(JSON.stringify({score: a?.score, displayValue: a?.displayValue, items: a?.details?.items}))"
- Run
4. Client-Side Cookie Inspection & Manipulation
For client-accessible, non-HttpOnly cookies (e.g., UI preferences, non-sensitive feature flags):
- Read Cookies & Attributes:
- Use the modern asynchronous Cookie Store API:
async () => await cookieStore.getAll(); - Fallback for insecure HTTP origins:
() => document.cookie.
- Use the modern asynchronous Cookie Store API:
- Set / Modify Cookie:
- Set client cookie via
cookieStore:async () => await cookieStore.set({ name: 'theme', value: 'dark', expires: Date.now() + 86400000, sameSite: 'lax', });
- Set client cookie via
- Delete Cookie:
- Clear client cookie:
async () => await cookieStore.delete('theme');
- Clear client cookie:
Troubleshooting
cookieStoreis undefined:cookieStorerequires a Secure Context (https://,localhost, or127.0.0.1). On non-secure HTTP origins, use() => document.cookieor test over HTTPS.evaluate_scriptreturns empty / unresolved Promise:cookieStoremethods are asynchronous. Always wrap calls withasync () => await cookieStore.getAll().- Cookie not visible in JavaScript: The cookie is marked
HttpOnly. Trigger a network request and callget_network_requestto view it in theCookierequest header. - JavaScript deletion did not remove cookie: The cookie is
HttpOnlyor requires matchingPathandDomainparameters. Use a freshisolatedContextwithnew_pagefor a clean slate. - Cookie set in response but not sent in requests:
- Verify if page is
http://while cookie specifiesSecure. - Check if
Domainrestricts subdomains. - Check
list_console_messages(types: ["issue"])for browser rejection reasons.
- Verify if page is
- Residual cookies contaminating audits: Always use
new_pagewith a uniqueisolatedContextwhen running compliance tests, and callclose_pagewhen done.
Version History
- 4a3f6fc Current 2026-09-09 14:06


