# Security Model for Storing Credentials and Cookies in Agent Reach's config.yaml

> Discover Agent Reach's security model for storing credentials and cookies in config.yaml. Learn about its three-layer defense for sensitive data protection.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: security
- Published: 2026-07-09

---

**Agent Reach stores all sensitive credentials in `~/.agent-reach/config.yaml` using a three-layer defense strategy: strict POSIX filesystem permissions (0o700/0o600), runtime masking of secret values, and atomic file creation with owner-only access flags.**

The **Panniantong/Agent-Reach** repository manages authentication secrets ranging from Twitter API tokens to XiaoHongShu session cookies. Understanding the **security model for storing credentials and cookies in Agent Reach** is essential for administrators deploying the tool on multi-user systems or shared development environments where unauthorized access to secrets could compromise automated agents.

## Filesystem Permissions and Access Control

Agent Reach enforces **owner-only filesystem permissions** at the operating system level to prevent unauthorized reads by other users on the same machine.

The configuration directory `~/.agent-reach` is created with mode `0o700` (read, write, and execute for owner only) through the `make_private_dir` function in **[`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py)**【/cache/repos/github.com/Panniantong/Agent-Reach/main/agent_reach/utils/paths.py#L10-L16】. This ensures that non-privileged users cannot list the directory contents or traverse into it.

The [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml) file itself receives mode `0o600` (read/write for owner only) through a secure creation pattern implemented in **[`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)**【/cache/repos/github.com/Panniantong/Agent-Reach/main/agent_reach/config.py#L54-L66】. The `Config.save()` method attempts to open the file using `os.open(..., stat.S_IRUSR | stat.S_IWUSR)`, which atomically creates the file with restricted permissions. If the operating system does not support these flags, the code falls back to a standard open followed by `os.chmod` to enforce `0o600`.

## Runtime Masking of Sensitive Values

To prevent accidental leakage in logs and UI output, Agent Reach implements **automatic masking** of secret values when the configuration is displayed.

The `Config.to_dict()` method in **[`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)** scans each configuration key for sensitive substrings including `key`, `token`, `cookie`, `session`, `csrf`, `auth`, `cred`, and `ct0`【/cache/repos/github.com/Panniantong/Agent-Reach/main/agent_reach/config.py#L108-L128】. When a match is detected, the method truncates the value to the first eight characters followed by an ellipsis, ensuring that debug output or CLI tables reveal only non-sensitive prefixes.

## External Sync and Auxiliary Storage

For backward compatibility with other tools, Agent Reach optionally synchronizes Twitter credentials to auxiliary locations while maintaining the same security standards.

The `_open_owner_only` helper function in **[`agent_reach/cookie_extract.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cookie_extract.py)** provides a reusable mechanism for creating files with `0o600` permissions【/cache/repos/github.com/Panniantong/Agent-Reach/main/agent_reach/cookie_extract.py#L49-L68】. This helper is utilized by two sync functions:
- `_sync_xfetch_session` writes to `~/.config/xfetch/session.json`【/cache/repos/github.com/Panniantong/Agent-Reach/main/agent_reach/cookie_extract.py#L75-L98】
- `_sync_bird_env` writes to `~/.config/bird/credentials.env`【/cache/repos/github.com/Panniantong/Agent-Reach/main/agent_reach/cookie_extract.py#L102-L124】

Both auxiliary files inherit the owner-only permission model, ensuring consistent protection across all credential storage locations.

## Credential and Cookie Flow

The complete lifecycle of secret storage follows four distinct stages:

1. **Extraction** – The `cookie_extract.extract_all()` function pulls cookies from browsers using `rookiepy` or `browser_cookie3`.
2. **Configuration** – The `configure_from_browser()` method writes extracted values into the Config instance via `config.set(key, value)`.
3. **Persistence** – Each `set()` call triggers `Config.save()`, which writes the YAML with restricted `0o600` permissions.
4. **Masking** – When callers request `config.to_dict()`, any secret value matching sensitive markers is masked before being returned.

The test suite in **[`tests/test_config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_config.py)** validates that directory and file permissions are correctly set to `0o700` and `0o600` respectively【/cache/repos/github.com/Panniantong/Agent-Reach/main/tests/test_config.py#L92-L104】, while also verifying that sensitive values appear masked in dictionary representations【/cache/repos/github.com/Panniantong/Agent-Reach/main/tests/test_config.py#L65-L71】.

## Practical Configuration Example

The following example demonstrates secure credential storage and retrieval:

```python
from agent_reach.config import Config

# Initialize creates ~/.agent-reach with 0o700 permissions

cfg = Config()  # Creates /home/user/.agent-reach/config.yaml

# Store secrets (file written with 0o600 atomic permissions)

cfg.set("twitter_auth_token", "my-super-secret-token")
cfg.set("xhs_cookie", "web_session=abc123; other=def456")

# Retrieve full value for API calls

token = cfg.get("twitter_auth_token")  # Returns full string

# Safe view for logging (automatically masked)

safe_cfg = cfg.to_dict()

# Output: {"twitter_auth_token": "my-supe...", "xhs_cookie": "web_ses..."}

```

## Summary

- **Agent Reach** stores credentials in `~/.agent-reach/config.yaml` with owner-only POSIX permissions (`0o600` for files, `0o700` for directories).
- The **`Config.save()`** method uses `os.open` with `stat.S_IRUSR | stat.S_IWUSR` flags to atomically create restricted files, falling back to `os.chmod` when necessary.
- **Runtime masking** in `Config.to_dict()` prevents secret leakage by truncating values containing sensitive markers (`token`, `cookie`, `auth`, etc.) to eight characters.
- Auxiliary credential files in `~/.config/xfetch/` and `~/.config/bird/` receive identical `0o600` permissions through the **`_open_owner_only`** helper.
- The implementation is validated by **[`tests/test_config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_config.py)**, which asserts correct permission bits and masking behavior.

## Frequently Asked Questions

### How does Agent Reach prevent other users from reading my API keys?

Agent Reach creates the configuration directory with `0o700` permissions and the [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml) file with `0o600` permissions using the `make_private_dir` function in [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py) and atomic file creation in `Config.save()`. These POSIX modes restrict read and write access exclusively to the file owner, preventing any other user on the system—including those with standard user privileges—from accessing your secrets.

### What happens if the atomic open with permission flags fails?

If the operating system does not support the `os.open` flags `stat.S_IRUSR | stat.S_IWUSR`, the code in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) falls back to a standard file open followed immediately by `os.chmod` to enforce `0o600` permissions. This ensures that even on limited platforms, the file does not remain world-readable even for a brief instant after creation.

### Why are my credential values truncated when I print the configuration?

The `Config.to_dict()` method automatically masks any value associated with keys containing sensitive substrings like `token`, `cookie`, `session`, or `auth`. This deliberate **defense-in-depth** measure prevents accidental exposure of full secrets in log files, debug traces, or CLI output, showing only the first eight characters followed by an ellipsis.

### Are credentials synced to external tools also protected?

Yes. When Agent Reach synchronizes Twitter credentials to `~/.config/xfetch/session.json` or `~/.config/bird/credentials.env`, it uses the `_open_owner_only` helper in [`agent_reach/cookie_extract.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cookie_extract.py). This function mirrors the secure file creation pattern of the main configuration, guaranteeing that auxiliary files also receive `0o600` permissions and remain accessible only to the owner.