# Agent Reach Credential Storage Security: How Secrets Are Protected

> Agent Reach secures your credentials in a single YAML file using 0o600 permissions environment variable fallbacks and automatic masking to prevent leakage.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: best-practices
- Published: 2026-06-06

---

**Agent Reach stores all API keys, OAuth tokens, and browser cookies in a single YAML file at `~/.agent-reach/config.yaml` with restrictive 0o600 file permissions, environment variable fallbacks, and automatic masking of sensitive values to prevent leakage.**

Agent Reach is an open-source agent framework that handles sensitive authentication credentials for various services. The project implements a comprehensive **Agent Reach credential storage security** model through a centralized configuration manager that ensures secrets are never world-readable and are masked in diagnostic output.

## Core Storage Architecture

### The Config Class Centralization

All credential read and write operations are encapsulated in the **`Config`** class located in [[`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py). This design ensures that every credential passes through a single, permission-controlled code path regardless of whether it is set via CLI, imported from browser cookies, or configured programmatically.

The configuration file resides at:

```

~/.agent-reach/config.yaml

```

The `_ensure_dir()` method creates this directory on first use with `mkdir(parents=True, exist_ok=True)`, guaranteeing the path exists before any write operation occurs.

### Strict File Permissions (0o600)

When saving credentials, the `Config.save()` method opens the file using low-level `os.open()` flags:

```python
os.open(path, flags, stat.S_IRUSR | stat.S_IWUSR)

```

This creates the file with mode **0o600** (read/write for owner only). If the low-level flags are unavailable (e.g., on Windows), the implementation falls back to a standard `open()` call, but the directory creation still minimizes exposure by ensuring the parent path exists with appropriate restrictions.

## Security Mechanisms

### Environment Variable Fallback

To support users who prefer not to store secrets on disk, `Config.get()` implements a priority lookup system:

1. First checks the YAML configuration file
2. Then falls back to environment variables via `os.environ.get(key.upper())`

This allows sensitive values to be injected at runtime without ever touching the filesystem, reducing the attack surface for credential theft.

### Sensitive Value Masking

When generating diagnostic output or debugging, `Config.to_dict()` automatically masks any key containing `"key"`, `"token"`, `"password"`, or `"proxy"`. The masking preserves only the first 8 characters followed by an ellipsis:

```python
cfg = Config()
print(cfg.to_dict())

# Output: {'github_token': 'ghp_XXXX...', 'exa_api_key': 'sk-abc12...'}

```

This prevents accidental exposure of full secrets in logs, stack traces, or CLI output.

### Legacy Sync Protection

When importing Twitter cookies, the helper functions in [[`agent_reach/cookie_extract.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cookie_extract.py)](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cookie_extract.py) write the same credentials to auxiliary third-party tool locations:

- `~/.config/xfetch/session.json`
- `~/.config/bird/credentials.env`

These files are also created with mode **0o600**, ensuring consistent security across the credential ecosystem even when syncing to external tool configurations.

## Practical Implementation Examples

### Storing Credentials via CLI

```bash

# Set a GitHub token securely

agent-reach configure github-token ghp_XXXXXXXXXXXXXXXXXXXX

```

Behind the scenes, the CLI in [[`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) parses this input and calls `config.set("github_token", value)`, which triggers the secure save routine.

### Programmatic Configuration

```python
from agent_reach.config import Config

cfg = Config()                     # loads ~/.agent-reach/config.yaml

cfg.set("exa_api_key", "sk-abc123")   # writes with 0o600 permissions

print(cfg.to_dict())               # => {'exa_api_key': 'sk-abc12...'}

```

### Environment Variable Override

```python
import os
os.environ["EXA_API_KEY"] = "sk-xyz987"

from agent_reach.config import Config
cfg = Config()

# Returns "sk-xyz987" from environment, not from file

key = cfg.get("exa_api_key")

```

### Verifying File Permissions

```bash
$ ls -l ~/.agent-reach/config.yaml
-rw------- 1 user user 1234 Jun  6 12:34 /home/user/.agent-reach/config.yaml

```

The `-rw-------` permission string confirms that only the file owner can read or write the configuration.

## Summary

- **Centralized storage**: All secrets reside in `~/.agent-reach/config.yaml` managed by the `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)
- **Strict permissions**: Files are created with mode 0o600 using `os.open()` with `stat.S_IRUSR | stat.S_IWUSR` flags
- **Flexible input**: `Config.get()` supports both file-based and environment variable sources, checking `os.environ` as a fallback
- **Leak prevention**: `Config.to_dict()` masks sensitive keys (containing "key", "token", "password", or "proxy") to prevent full secret exposure
- **Third-party sync**: Cookie extraction utilities maintain 0o600 permissions when writing to auxiliary files like `~/.config/xfetch/session.json`

## Frequently Asked Questions

### Where does Agent Reach store API keys and tokens?

Agent Reach stores all credentials in a single YAML file located at `~/.agent-reach/config.yaml`. The `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) manages all read and write operations to this file, ensuring consistent security controls.

### What file permissions does Agent Reach use for credential storage?

The implementation uses mode **0o600** (owner read/write only) via `os.open()` with `stat.S_IRUSR | stat.S_IWUSR` flags. This prevents other users on the system from accessing the configuration file, and unit tests in [`tests/test_config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_config.py) verify these permissions are correctly applied.

### How does Agent Reach prevent credentials from appearing in logs?

The `to_dict()` method automatically masks any configuration key containing "key", "token", "password", or "proxy", showing only the first 8 characters followed by an ellipsis. This ensures that debug output and diagnostic dumps never reveal complete secret values.

### Can I use environment variables instead of the config file?

Yes. The `Config.get()` method checks for environment variables using `os.environ.get(key.upper())` before falling back to the YAML file. This allows you to keep secrets exclusively in environment variables if your security policy prohibits on-disk storage.