* add security hardening features
- Add authentication vault (`auth save/login/list/show/delete`) so credentials are stored locally and never exposed to the LLM (fixes Snyk W007)
- Add `--content-boundaries` flag to wrap page-sourced output in structural markers, helping LLMs distinguish tool output from untrusted page content (fixes Snyk W011)
- Add `--allowed-domains` flag to restrict browser navigation to trusted domains
- Add `--action-policy` for static allow/deny gating of action categories, with opt-in `--confirm-actions`/`--confirm-interactive` for orchestrator or human-in-the-loop confirmation
- Add `--max-output` flag to truncate large page outputs, preventing context flooding
- New docs page at /security, updated README, SKILL.md, CLI help text, and templates
* fixes
* fixes
* fixes
* fixes
* fixes
* fixes
* fixes
* docs
- Add AGENT_BROWSER_DEFAULT_TIMEOUT env var to override Playwright's
default 60s timeout (CDP/recording 10s timeouts unaffected)
- Add backpressure-aware safeWrite() that waits for drain when socket
buffer is full, preventing data loss under load
- Serialize command execution per socket via queue to prevent concurrent
writes that cause buffer contention
These daemon-side fixes complement #329 (CLI-side EAGAIN retry) by
addressing the root causes: Playwright operations that outlast the
CLI's IPC timeout, and concurrent socket.write() calls that overflow
the kernel buffer.
Tested with heavy React app (1000+ DOM nodes) — 10 consecutive
snapshot commands complete without os error 35/11.
Refs #322
Co-authored-by: shohu <shohu@users.noreply.github.com>
Fixes#519. Playwright defaults `colorScheme` to `light` on all new contexts, overriding the browser/OS dark mode setting. This is especially disruptive in CDP mode, where every reconnection resets the scheme. The `set media dark` command also didn't persist its choice to new tabs or pages.
- Add `--color-scheme <dark|light|no-preference>` flag, config key (`colorScheme`), and env var (`AGENT_BROWSER_COLOR_SCHEME`)
- Store the preference in `BrowserManager` and automatically apply it to all new contexts (via Playwright's context option) and all new pages (via `page.emulateMedia` in `setupPageTracking`)
- `set media dark/light` now also persists its choice for subsequent pages and tabs
`state load` always fails with "Cannot load state while browser is running" even when no browser is running, making the command completely unusable (#526).
The daemon's auto-launch logic starts a browser before `state_load` gets to handle the command. This adds `state_load` to the exclusion list alongside `launch` and `close`, so `handleStateLoad` can perform its own launch with the state file.
Rebased and fixed implementation of PR #184 features on current main:
Session persistence:
- --session-name flag and AGENT_BROWSER_SESSION_NAME env var auto-save/restore
cookies and localStorage across browser restarts
- State files stored in ~/.agent-browser/sessions/ with owner-only permissions
- AES-256-GCM encryption via AGENT_BROWSER_ENCRYPTION_KEY env var
- Auto-expiration of old state files (AGENT_BROWSER_STATE_EXPIRE_DAYS, default 30)
State management commands:
- state list: list saved state files with metadata
- state show <file>: display state summary (cookies, origins, domains)
- state rename <old> <new>: rename state files
- state clear [name] [--all]: clear saved states
- state clean --older-than <days>: delete expired states
New --new-tab flag for click command:
- Opens link href in a new tab instead of navigating the current tab
Security hardening:
- Session name validation prevents path traversal (CLI + daemon)
- safeHeaderMerge prevents prototype pollution in header merging
- WebSocket stream server binds to 127.0.0.1 only
- State files written with 0o600 permissions
Fixes applied over the original PR:
- Use color.rs module instead of hardcoded ANSI escape codes
- Align CLI output field names with daemon response format
- Add CLI-level --session-name validation (not just daemon-side)
- Avoid adding "DOM" to tsconfig.json lib (use proper typing in evaluate)
- Keep version at 0.9.3 (matches current main)
- Centralize session name validation in daemon.ts helper
- Update all documentation (README, SKILL.md, docs site, --help output)
Co-authored-by: Chris Tate <chris@ctate.dev>
* feat: add --allow-file-access flag for file:// URL support
Adds the ability to open and interact with local files using file:// URLs.
This enables use cases like viewing local PDFs, testing local HTML files,
and allowing JavaScript to access other local files via XHR.
The flag adds Chromium's --allow-file-access-from-files and --allow-file-access
launch arguments. Only supported in Chromium browsers.
Fixes#345
* fix: add cli_allow_file_access tracking to prevent spurious warning
When --allow-file-access is set via AGENT_BROWSER_ALLOW_FILE_ACCESS env var
(not CLI), don't warn about the flag being ignored when daemon is already running.
* fix(cli): save screenshots to tmp dir when no path provided
Instead of outputting base64 to stdout (which is not useful for most CLI use cases),
screenshots without a path now save to ~/.agent-browser/tmp/screenshots/ with a
generated filename and return the path.
This makes the behavior more ergonomic for AI agents and CLI users alike.
* cleanup
* cleanup
* just revert the cargo.lock version for now
* refactor: extract getAppDir() from getSocketDir()
* docs: improve screenshot help text consistency
* feat: add support for ignoring HTTPS certificate errors
* fix: update warning message for already running daemon to include ignore HTTPS errors option
* docs: add documentation for --ignore-https-errors option in README and SKILL.md
* feat: initialize ignore_https_errors flag in command context
* fix: change launch_cmd to mutable for cdp value handling
* fix: use ~/.agent-browser for socket files instead of TMPDIR
This fixes issue #163 where different TMPDIR values (common with
tmux/screen/VSCode/IntelliJ) caused the CLI and daemon to use
different socket paths.
Socket directory priority:
1. AGENT_BROWSER_SOCKET_DIR (explicit override)
2. $XDG_RUNTIME_DIR/agent-browser (Linux standard)
3. ~/.agent-browser (fallback, like Docker Desktop)
Both CLI (Rust) and daemon (Node.js) now use the same logic.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: session list now looks in correct socket directory
- Make get_socket_dir() public in connection.rs
- Update session list to use get_socket_dir() instead of temp_dir()
- Update pid file pattern from agent-browser-{session}.pid to {session}.pid
- Add tmpdir fallback to daemon.ts when homedir is unavailable
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add unit tests for socket directory resolution
Add comprehensive tests for get_socket_dir/getSocketDir to verify:
- AGENT_BROWSER_SOCKET_DIR takes priority
- Empty strings are ignored (fixes Rust/TypeScript consistency)
- XDG_RUNTIME_DIR fallback works correctly
- Home directory fallback when env vars unset
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The headless option was hardcoded to true in the auto-launch section,
ignoring the AGENT_BROWSER_HEADED environment variable. This fix checks
the env var so users can run the browser in headed mode by setting
AGENT_BROWSER_HEADED=1.
Fixes#90
2026-01-17 19:22:59 -06:00
Chris TateandVercel <vercel[bot]@users.noreply.github.com>