Preserve cookie security attributes in updateCookies round-trip
Chromium's Cookies() API can lose or normalize Secure, SameSite, and HttpOnly attributes during the AddCookies → navigate → Cookies() round-trip. This caused cookies like cf_clearance (set with Secure=true, SameSite=None) to be overwritten with Chromium's defaults (Secure=false, SameSite=Lax). Now updateCookies() looks up existing cookies in the jar first. For cookies that already exist, only Value and Expires are updated — security attributes are preserved from the original. New cookies from the server are still written with all their attributes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -219,11 +219,35 @@ func (b playWrightBrowser) updateCookies(_ context.Context, page playwright.Page
|
|||||||
return fmt.Errorf("error getting cookies from browser: %w", err)
|
return fmt.Errorf("error getting cookies from browser: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build a lookup of existing cookies so we can preserve their security
|
||||||
|
// attributes. Chromium's Cookies() API can lose or normalize Secure,
|
||||||
|
// SameSite, and HttpOnly during the AddCookies → navigate → Cookies()
|
||||||
|
// round-trip, so we only update Value and Expires for cookies that
|
||||||
|
// already exist in the jar.
|
||||||
|
existing, err := b.cookieJar.Get(page.URL())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting existing cookies from jar: %w", err)
|
||||||
|
}
|
||||||
|
type cookieKey struct{ Name, Path string }
|
||||||
|
existingMap := make(map[cookieKey]Cookie, len(existing))
|
||||||
|
for _, c := range existing {
|
||||||
|
existingMap[cookieKey{c.Name, c.Path}] = c
|
||||||
|
}
|
||||||
|
|
||||||
for _, cookie := range cookies {
|
for _, cookie := range cookies {
|
||||||
// TODO: add support for deleting cookies from the jar which are deleted in the browser
|
// TODO: add support for deleting cookies from the jar which are deleted in the browser
|
||||||
err = b.cookieJar.Set(playwrightCookieToCookie(cookie))
|
c := playwrightCookieToCookie(cookie)
|
||||||
|
|
||||||
if err != nil {
|
if prev, ok := existingMap[cookieKey{c.Name, c.Path}]; ok {
|
||||||
|
// Preserve the original security attributes; only update
|
||||||
|
// Value and Expires which are the fields that legitimately
|
||||||
|
// change during navigation.
|
||||||
|
c.Secure = prev.Secure
|
||||||
|
c.HttpOnly = prev.HttpOnly
|
||||||
|
c.SameSite = prev.SameSite
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = b.cookieJar.Set(c); err != nil {
|
||||||
return fmt.Errorf("error setting cookie in cookie jar: %w", err)
|
return fmt.Errorf("error setting cookie in cookie jar: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user