cookie-import-browser: most cookies silently dropped — imports 3 of 22 for Arc Profile N
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
## Summary
`cookie-import-browser arc --domain --profile "Profile 14"` imports only 3 of 22 valid, non-expired cookies for `.slack.com`. The `d` cookie (Slack's session auth) is among the dropped ones, so downstream browse sessions get redirected to login on every authenticated URL.
All 22 cookies are `v10`-encrypted (plaintext Keychain password scheme). The failure is silent — the CLI only reports `Imported 3 cookies for slack.com from arc`, no indication that 19 failed.
## Environment
- gstack: `1.0.0.0` (upgraded from `0.17.0.0` during investigation — same behavior on both)
- macOS, Apple Silicon
- Arc: current stable, 5 profiles (`Default` + `Profile 11` — `Profile 14`)
- Arc fully running / logged-in to the target site in `Profile 14`
## Reproduction
```bash
# Confirm target profile has the cookies (all v10)
DB="$HOME/Library/Application Support/Arc/User Data/Profile 14/Cookies"
sqlite3 "$DB" "SELECT SUBSTR(encrypted_value,1,3) AS ver, COUNT(*) FROM cookies WHERE host_key LIKE '%slack%' GROUP BY ver"
# Output: v10|32
# Run the import
B=~/.claude/skills/gstack/browse/dist/browse
$B goto https://.slack.com
$B cookie-import-browser arc --domain slack.com --profile "Profile 14"
# Output: "Imported 3 cookies for slack.com from arc"
```
## Expected
All 22 unexpired `.slack.com` cookies are imported (or the CLI reports the `failed` count it already tracks internally — see `importCookies` line 283 in `cookie-import-browser.ts`).
## Actual
Only 3 cookies imported: `b`, `x`, `OptanonConsent`. The useful HttpOnly session cookies (`d`, `d-s`, and 17 others) are silently dropped.
Verified via `$B cookies | jq '.[] | select(.domain | test("slack"))'` after import.
## Pattern in the data
From `sqlite3 "$DB" "SELECT name, SUBSTR(encrypted_value,1,3) ver, LENGTH(encrypted_value) len, is_httponly, is_secure FROM cookies WHERE host_key = '.slack.com'"`:
| name | ver | len | httponly | secure | imported |
|---|---|---|---|---|---|
| b | v10 | 83 | 0 | 1 | ✅ |
| x | v10 | 83 | 0 | 1 | ✅ |
| OptanonConsent | v10 | 387 | 0 | 0 | ✅ |
| d | v10 | 275 | **1** | 1 | ❌ |
| d-s | v10 | 51 | **1** | 1 | ❌ |
| _cs_id | v10 | 131 | 0 | 1 | ❌ |
| _ga | v10 | 67 | 0 | 0 | ❌ |
| _ga_QTJQME5M5D | v10 | 83 | 0 | 0 | ❌ |
| ... 14 more dropped ... | | | | | |
The 3 imported vs 19 dropped split does not cleanly correlate with `is_httponly`, `is_secure`, or `length`. `b` and `_ga_QTJQME5M5D` are both length 83, `is_httponly=0`, `is_secure`=1/0 respectively — one imports, the other doesn't.
Hypothesis: Arc's Keychain password / key-derivation may have rotated, and the 3 successful decrypts are cookies written since the last rotation. The older cookies can't be decrypted with the current Keychain entry. gstack's `decryptCookieValue` throws and is caught silently at `cookie-import-browser.ts:282-284`:
```ts
try {
const value = decryptCookieValue(row, derivedKeys, match.platform);
const cookie = toPlaywrightCookie(row, value);
cookies.push(cookie);
domainCounts[row.host_key] = (domainCounts[row.host_key] || 0) + 1;
} catch {
failed++;
}
```
`failed` is tracked but never surfaced — the CLI and UI report only the success count.
## Suggested fixes (any one helps)
1. **Surface `failed` count in the CLI output** — at minimum log `Imported 3 cookies (19 failed to decrypt) for slack.com from arc` so the user knows something's off.
2. **Log the decrypt exception** (behind `DEBUG=1`) — helps diagnose per-cookie failures.
3. **Try multiple Keychain entries / fallback derivation schemes** if the primary password fails for some rows — matches what `decrypt-chrome-cookies` does.
4. **UI picker**: currently returns `Failed to fetch` when trying to import `.slack.com` — likely the same underlying decrypt error but wrapped as a server error. Should show partial success.
## Impact
Any gstack workflow that requires importing an authenticated session from Arc into headless browse (`/qa` on authenticated pages, Slack/Notion/internal-app QA, `setup-browser-cookies` skill) silently fails — the cookies are "imported" but the critical auth cookie is missing, so the next navigation 302s to login. User sees no error; only discovers the problem when auth doesn't work.
/cc anyone maintaining `src/cookie-import-browser.ts`
Contributor guide
Assessment
This issue has not been assessed yet.