# How Agent Reach Handles Credential Storage and Security: A Deep Dive into the Config Module

> Agent Reach secures credential storage using a YAML file with 0o600 permissions and env variable fallbacks. Learn how config module prevents credential leakage.

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

---

**Agent Reach stores all user secrets in a single YAML file at `~/.agent-reach/config.yaml` with strict 0o600 file permissions, environment variable fallbacks, and automatic masking of sensitive values to prevent credential leakage.**

Agent Reach is an open-source automation framework that requires users to provide sensitive credentials like API keys and OAuth tokens. Understanding how the repository handles credential storage and security is essential for anyone deploying the tool in production environments, as the design deliberately avoids storing secrets in source code or committing them to version control.

## Where Credentials Are Stored

### The Config File Location

All user-provided secrets—including API keys, OAuth tokens, and browser cookies—are persisted to a single YAML file located in the user's home directory:

```bash
~/.agent-reach/config.yaml

```

This centralized approach ensures that credentials are never scattered across multiple configuration files or embedded in environment scripts.

### Directory Structure and Creation

The **`Config`** class 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) creates the containing directory on first use via the `_ensure_dir()` method. This guarantees that the path exists before any write operation occurs, minimizing the risk of failures or permission inheritance issues from parent directories.

## Security Mechanisms in the Config Module

### Strict File Permissions (0o600)

When saving the configuration, the `Config.save()` method uses low-level file operations to enforce owner-only access:

```python
os.open(..., stat.S_IRUSR | stat.S_IWUSR)  # mode 0o600

```

This translates to **read and write permissions exclusively for the file owner**, with no access for group members or others. If the low-level flags are unavailable (for example, on Windows), the code falls back to a standard `open()` call, but the directory creation still uses `mkdir(parents=True, exist_ok=True)` to minimize exposure.

You can verify these permissions from the command line:

```bash
ls -l ~/.agent-reach/config.yaml

# Output: -rw------- 1 user user 1234 Jun  6 12:34 /home/user/.agent-reach/config.yaml

```

The `-rw-------` mode confirms that only the owner can read or modify the credential store.

### Environment Variable Fallback

The `Config.get()` method implements a secure lookup chain that prioritizes environment variables over the filesystem. When retrieving a value, it first checks the YAML file, then falls back to `os.environ.get(key.upper())`. This allows users to keep secrets exclusively in their shell environment, avoiding accidental disclosure through the config file while maintaining backward compatibility with file-based storage.

### Sensitive Value Masking

To prevent credential leakage in diagnostic output, the `Config.to_dict()` method masks any key containing `"key"`, `"token"`, `"password"`, or `"proxy"`. It returns only the first 8 characters followed by an ellipsis (e.g., `abcd1234...`) when displaying these values. This ensures that logs, debug output, and CLI displays never expose full secrets even when the configuration is printed.

### Centralized Write Path

All CLI commands and helper functions (such as cookie extraction) store credentials through the `Config.set()` method. This guarantees that any write operation passes through the same permission-controlled routine 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), preventing ad-hoc file operations that might bypass security controls.

## Third-Party Tool Integration

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 secrets to legacy locations for compatibility:

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

Both files are created with the same **mode 0o600** permissions, ensuring that auxiliary credential stores receive equal protection even when syncing with external tools.

## Practical Implementation Examples

### Storing Credentials via CLI

Set a GitHub token using the command-line interface:

```bash
agent-reach configure github-token ghp_XXXXXXXXXXXXXXXXXXXX

```

Behind the scenes, the CLI parses the value, calls `config.set("github_token", value)`, and the `Config.save()` routine writes the file with secure permissions.

### Programmatic Configuration

Use the `Config` class directly in Python for automation:

```python
from agent_reach.config import Config

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

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

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

```

### Reading with Environment Fallback

When the environment variable exists but the file does not contain the key:

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

from agent_reach.config import Config
cfg = Config()
key = cfg.get("exa_api_key")   # Returns "sk-xyz987" from environment

```

## Summary

- **Agent Reach stores all credentials in `~/.agent-reach/config.yaml` with mode 0o600**, ensuring only the owner can read or write the file.
- **The `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) centralizes all read/write operations**, providing a single point of control for credential security.
- **Environment variables take precedence over file storage**, allowing users to avoid persisting secrets to disk when preferred.
- **Sensitive values are automatically masked in `to_dict()` output**, preventing accidental exposure in logs and debug output.
- **Third-party integrations in [`agent_reach/cookie_extract.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cookie_extract.py) maintain the same permission standards**, applying 0o600 to auxiliary credential files like `~/.config/xfetch/session.json`.

## Frequently Asked Questions

### Where does Agent Reach store API keys?

Agent Reach stores API keys and other secrets in a YAML file located at `~/.agent-reach/config.yaml` in the user's home directory. This location is created automatically by the `Config` class the first time a credential is saved.

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

The repository uses **mode 0o600** (owner read/write only) for all credential files. 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), the `Config.save()` method explicitly sets these permissions using `os.open()` with `stat.S_IRUSR | stat.S_IWUSR` flags.

### Does Agent Reach support environment variables for secrets?

Yes. The `Config.get()` method checks for environment variables using `os.environ.get(key.upper())` as a fallback after checking the config file. This allows users to override file-based credentials or avoid storing sensitive values on disk entirely.

### How does Agent Reach prevent leaking credentials in logs?

The `Config.to_dict()` method automatically masks values for any key containing `"key"`, `"token"`, `"password"`, or `"proxy"`, displaying only the first 8 characters followed by an ellipsis. This ensures that diagnostic output and CLI displays never reveal complete secrets.