Security Practices for Storing Cookies and Tokens in Agent‑Reach

Agent‑Reach enforces strict owner-only file permissions (mode 0o600), protected directories (mode 0o700), and atomic file creation to ensure authentication cookies and tokens remain inaccessible to other users on the system.

Agent‑Reach is an open‑source tool that extracts and manages authentication data from web browsers, requiring robust safeguards for sensitive credentials on disk. The codebase treats cookies and tokens as high‑value assets, implementing POSIX permission controls and atomic filesystem operations to eliminate exposure windows. These security practices for storing cookies and tokens are enforced across the cookie extraction logic, configuration management, and legacy compatibility layers.

Restrict File Access with Owner‑Only Permissions (0o600)

The foundation of Agent‑Reach’s security model is the owner‑only file permission mode 0o600 (read/write for the file owner only). All credential files, including browser‑extracted cookies and API tokens, are created using the _open_owner_only() helper function in agent_reach/cookie_extract.py.

This function opens files with the flags O_WRONLY | O_CREAT | O_TRUNC and passes the explicit mode stat.S_IRUSR | stat.S_IWUSR (0o600) to os.open(). By setting the permission atomically at creation time, the system guarantees the file never exists with default world‑readable permissions.

The configuration persistence layer in agent_reach/config.py reuses this primitive. When Config.save() writes the user’s settings—including stored authentication tokens—it invokes _open_owner_only(), ensuring the JSON or YAML configuration file inherits the same restrictive permissions.

Harden Directory Permissions (0o700)

Securing individual files is insufficient if surrounding directories allow traversal or listing by other users. Agent‑Reach addresses this by creating parent directories with mode 0o700 (rwx for owner only) using the make_private_dir() utility.

The standard storage location ~/.agent-reach and the legacy fallback ~/.config/xfetch both receive this treatment. This prevents unauthorized users from discovering credential filenames through directory listings or accessing files via path traversal on systems where the parent permissions might otherwise permit it.

Eliminate Race Conditions with Atomic Creation

A critical vulnerability in credential storage is the time‑of‑check to time‑of‑use race condition, where a file is created with default permissions and only later restricted via chmod(). Agent‑Reach eliminates this window by specifying permissions during the initial open() system call.

The _open_owner_only() implementation attempts to use os.open() with mode 0o600 directly. On platforms where these flags are unsupported (such as Windows), the code falls back to a standard open() followed immediately by os.chmod(path, 0o600), minimizing the exposure interval.

Runtime Permission Verification

Agent‑Reach defends against misconfigured environments by verifying and tightening permissions on existing files. When loading cookie files like xhs-cookies.json, the CLI checks current permissions using _owner_only() and _owner_only_dir() helpers. If a user manually created a file with lax permissions, the tool automatically corrects them to 0o600 before processing the credentials.

This self‑healing behavior is validated by unit tests in tests/test_cookie_extract_perms.py and tests/test_config.py, which assert that files and directories maintain expected permissions after creation and after programmatic tightening.

Implementation Examples

The following patterns demonstrate how to implement these security practices when storing sensitive data:

from pathlib import Path
import json

def _open_owner_only(path: str):
    """
    Open *path* for writing, atomically creating it with mode 0o600.
    """
    import os, stat
    try:
        fd = os.open(
            path,
            os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
            stat.S_IRUSR | stat.S_IWUSR,   # 0o600

        )
        if os.name != "nt":
            os.chmod(path, stat.S_IRUSR | stat.S_IWUSR)
        return os.fdopen(fd, "w", encoding="utf-8")
    except OSError:
        handle = open(path, "w", encoding="utf-8")
        if os.name != "nt":
            os.chmod(path, 0o600)
        return handle

# Usage: Writing XiaoHongShu cookies

cookie_path = Path.home() / ".agent-reach" / "xhs-cookies.json"
with _open_owner_only(str(cookie_path)) as f:
    json.dump({"cookie_string": cookie_str}, f, indent=2)

Creating a Protected Directory

from agent_reach.utils.paths import make_private_dir
from pathlib import Path

# Creates ~/.agent-reach with mode 0o700 if it does not exist

make_private_dir(Path.home() / ".agent-reach")

Saving Configuration Tokens Securely


# In agent_reach/config.py → Config.save()

with _open_owner_only(self.config_path) as f:
    json.dump(self._data, f, indent=2)

Legacy Session Synchronization

The _sync_xfetch_session() function in agent_reach/cookie_extract.py demonstrates backward‑compatible secure storage by writing the legacy xfetch session file using the same _open_owner_only() primitive:

def _sync_xfetch_session(auth_token: str, ct0: str) -> None:
    from agent_reach.utils.paths import make_private_dir
    import os, json
    
    xfetch_dir = os.path.join(os.path.expanduser("~"), ".config", "xfetch")
    make_private_dir(xfetch_dir)
    session_path = os.path.join(xfetch_dir, "session.json")
    
    # ... load existing JSON if present ...

    session_data = {"auth_token": auth_token, "ct0": ct0}
    
    with _open_owner_only(session_path) as sf:
        json.dump(session_data, sf, indent=2)

Summary

Agent‑Reach implements comprehensive security practices for storing cookies and tokens through the following measures:

  • Atomic file creation with mode 0o600 via _open_owner_only() ensures credentials are never written with world‑readable permissions.
  • Directory isolation using mode 0o700 via make_private_dir() prevents unauthorized discovery and traversal of credential storage paths.
  • Runtime hardening automatically tightens permissions on existing files that may have been created with insecure defaults.
  • Cross‑platform fallbacks maintain security posture on Windows and other platforms where POSIX flags may be unavailable.
  • Test enforcement via test_cookie_extract_perms.py and test_config.py guarantees these protections persist across code changes.

Frequently Asked Questions

Agent‑Reach creates all credential files with mode 0o600 (owner read/write only). This is enforced atomically at file creation time through the _open_owner_only() helper in agent_reach/cookie_extract.py, which passes stat.S_IRUSR | stat.S_IWUSR to os.open().

How does Agent‑Reach prevent race conditions when creating credential files?

The codebase eliminates race conditions by specifying the restrictive mode 0o600 during the initial open() system call rather than creating the file and subsequently calling chmod(). On platforms where atomic creation with permissions is unsupported, it immediately follows the open() with chmod(path, 0o600) to minimize the exposure window.

Does Agent‑Reach protect legacy configuration directories?

Yes. The function _sync_xfetch_session() in agent_reach/cookie_extract.py creates the legacy ~/.config/xfetch directory using make_private_dir(), which applies mode 0o700. This ensures backward compatibility with older xfetch configurations while maintaining the same security posture as the modern ~/.agent-reach path.

How does the CLI handle existing files with insecure permissions?

When loading existing cookie files (such as xhs-cookies.json), the CLI verifies permissions using _owner_only() and _owner_only_dir(). If a file is detected with permissions more permissive than 0o600, the tool automatically tightens them before reading the credentials, protecting against manual misconfiguration or restored backups with incorrect modes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →