Skip to content

Cookie store picks up cookies from interrupted requests, causing auth/nonce issues #3061

@adamziel

Description

@adamziel

Summary

When multiple client.goTo() calls happen in quick succession (e.g., redirect to homepage immediately followed by redirect to editor), both requests arrive at the server with no cookies. Each request independently tries to log the user in, setting different session cookies. The cookie store picks up cookies from both requests, including the interrupted one, which corrupts the session state and breaks nonces.

Steps to reproduce

  1. Call client.goTo('/wp-admin/')
  2. Immediately call client.goTo('/wp-admin/post-new.php') before the first navigation completes
  3. Observe that the session cookies get mixed up

Root cause

The data flow in this scenario:

  1. First request (homepage redirect) is sent with no cookies
  2. Second request (editor redirect) interrupts the first, also sent with no cookies
  3. Both requests independently hit the auto-login endpoint
  4. Both requests set different session cookies (sec cookie changes between them)
  5. The HttpCookieStore in php-request-handler.ts stores cookies from both responses, including the interrupted request
  6. This corrupts the session - nonces generated by one request don't match the session established by the other

With regular browser cookies, you'd simply get logged out (clearly indicating something is wrong). But because we use a custom cookie store that accumulates cookies from all responses, we end up with a corrupted but "logged in" state.

Relevant code

  • packages/php-wasm/universal/src/lib/http-cookie-store.ts - stores cookies from all responses
  • packages/php-wasm/universal/src/lib/php-request-handler.ts:665-668 - calls rememberCookiesFromResponseHeaders after every request

Possible solutions

  1. Don't store cookies from interrupted/cancelled requests - Track which requests are still "active" and only persist cookies from completed navigations

  2. Await navigation completion after every goTo() call - Callers should wait for the iframe to fully load before issuing another goTo(). This is a usage pattern fix rather than a Playground fix.

  3. Implement request sequencing - Queue goTo() calls so they execute one at a time, preventing overlapping requests

  4. Add request correlation to cookie storage - Associate cookies with specific request IDs and only keep cookies from the "winning" request in case of races

Metadata

Metadata

Assignees

No one assigned

    Labels

    [Type] BugAn existing feature does not function as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions