Skip to content

fix(cookie-extract): let --from-browser target a specific Chrome profile#526

Open
LucasRollo wants to merge 3 commits into
Panniantong:mainfrom
LucasRollo:fix/chrome-profile-cookie-extraction
Open

fix(cookie-extract): let --from-browser target a specific Chrome profile#526
LucasRollo wants to merge 3 commits into
Panniantong:mainfrom
LucasRollo:fix/chrome-profile-cookie-extraction

Conversation

@LucasRollo

Copy link
Copy Markdown

Problem

agent-reach configure --from-browser chrome (and the auto-import during install) silently reads cookies from the Default Chrome profile only, with no way to pick another profile.

Both extraction backends resolve to the first matching cookie DB and stop:

  • browser_cookie3's Chrome path list is ['.../Default/Cookies', '.../Profile */Cookies'] and it returns the first glob match (next(...)), so Default always wins when present.
  • rookiepy does the same in its Rust find_chrome_based_paths (first existing path wins, early return), and exposes no profile parameter through its Python API.

This directly undercuts the project's own security guidance. The README and docs/install.md recommend using a dedicated/secondary account for cookie-auth platforms (Twitter, XHS, Reddit, etc.). The natural way to do that is a separate Chrome profile for burner accounts — but with this bug, extraction ignores that profile and grabs cookies from the user's real Default profile instead. The safe workflow the docs recommend can't actually be followed.

Fix

  • list_chrome_profiles(browser) — enumerates profiles from the browser's own Local State file (the same source Chrome's profile picker uses), returning each profile's folder, display name, account email, and exact Cookies DB path. Supports chrome/edge/brave/opera across macOS/Windows/Linux.
  • extract_all() / configure_from_browser() — new optional profile= parameter. When set, it resolves that profile's exact cookie DB and routes through browser_cookie3(cookie_file=...) (rookiepy has no profile override). When omitted, behavior is byte-for-byte unchanged — no regression for existing users.
  • CLI --chrome-profile flag — when multiple profiles exist and none is specified: prompts interactively (numbered list with name + email) at a TTY; otherwise lists the available folders and aborts rather than silently guessing.

Tests

  • tests/test_cookie_extract_profiles.py — profile discovery, missing/empty Local State, profiles without a Cookies DB yet, the core regression (right profile → right cookie path), and the two error paths (unknown profile, firefox+profile).
  • Full existing suite still passes (202 passed on Python 3.12).

Example

$ agent-reach configure --from-browser chrome
Found 2 chrome profiles:
  1. Lucas (main) (real@gmail.com)  [Default]
  2. Research (burner@gmail.com)  [Profile 1]
Which profile has the accounts you want? [1-2]: 2

# or non-interactively:
$ agent-reach configure --from-browser chrome --chrome-profile "Profile 1"

LucasRollo and others added 3 commits July 23, 2026 16:21
rookiepy and browser_cookie3 both resolve to the first matching cookie
database — in practice always the "Default" profile — with no way to
target another profile from their public APIs. Anyone keeping research
accounts in a separate Chrome profile (as README's dedicated-account
guidance suggests) would have `agent-reach configure --from-browser
chrome` silently read cookies from their real Default profile instead.

- add list_chrome_profiles(): enumerate profiles from the browser's own
  Local State file (name, email, exact Cookies DB path); supports
  chrome/edge/brave/opera on macOS/Windows/Linux
- extract_all()/configure_from_browser(): new optional profile= param;
  when set, routes through browser_cookie3 with an explicit cookie_file
  (rookiepy has no profile override). No profile given = behavior
  unchanged
- CLI: new --chrome-profile flag; when several profiles exist and no
  flag is given, prompt interactively at a TTY, or list the folders and
  abort instead of guessing when non-interactive

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Explain how to extract cookies from a non-Default Chrome profile (the
recommended setup for keeping burner/research accounts out of your main
profile), how to find a profile's folder name (run the command, or
chrome://version → Profile Path), and that only Chromium browsers
support per-profile extraction. Adds matching Quick Reference rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n correctly

Self-review of the --chrome-profile feature turned up several issues:

- Picker accepted "0"/negative input and silently selected the WRONG
  profile: profiles[int(choice)-1] with only ValueError/IndexError guards
  let int("0")-1 == -1 resolve to profiles[-1] (the last profile). Extract
  the choice-parsing into _resolve_profile_choice() with an explicit
  1<=n<=len bound, and unit-test 0 / negative / out-of-range / non-numeric.
- Opera can't actually be targeted by profile (it's Chromium-based but has
  no Default/Profile N folders, and on Windows lives under %APPDATA% not
  %LOCALAPPDATA%). Dropped it from the profile table so profile selection
  is chrome/edge/brave only; opera still works for plain extraction. An
  explicit --chrome-profile on opera/firefox now fails with a clear message.
- Requesting a profile on a rookiepy-only install raised a message telling
  you to install rookiepy (already present); now it names browser_cookie3
  as the actual requirement for profile mode.
- --chrome-profile help text no longer claims you're "prompted" in cases
  where the non-interactive path aborts instead.
- Deduped a double Local State read on the not-found path; sort profiles
  numerically so "Profile 10" follows "Profile 2"; handle EOF at the prompt;
  clearer "profile exists but has no cookies yet" hint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant