# Agent Reach config.yaml Security Model: How Credentials Are Stored and Protected

> Discover how Agent Reach secures API keys in config.yaml with strict file permissions, isolated directories, and automatic masking. Learn about its robust credential storage and protection.

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

---

**Agent Reach secures API keys and tokens in `~/.agent-reach/config.yaml` using 600 file permissions (user-only access), isolated directory creation, and automatic masking of sensitive values in CLI output.**

The Agent Reach framework implements a defense-in-depth strategy for credential storage through its `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py). This design combines Unix filesystem permissions with application-level safeguards to ensure secrets remain accessible only to the owning user while preventing accidental exposure in logs or terminal output.

## Isolated Configuration Directory

Agent Reach confines all user-specific data to a dedicated hidden directory. Upon first initialization, the `_ensure_dir` method automatically creates `~/.agent-reach/` if it does not exist.

This isolation prevents credential scattering across the filesystem. By centralizing configuration in a single location rather than using temporary files or system-wide directories, the tool reduces the attack surface and simplifies permission auditing.

## Filesystem-Level Permission Controls

When writing the YAML file, Agent Reach enforces strict access controls using low-level system calls. In the `save` method (lines 52-60 of [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)), the code opens the file with `os.open` using the flags `stat.S_IRUSR | stat.S_IWUSR`, which corresponds to octal `0o600`.

This permission mask guarantees that **only the file owner** can read or write the configuration. The implementation eliminates race conditions where credentials might temporarily be world-readable during file creation. For platforms where these low-level flags are unavailable (such as Windows), the code falls back to a standard `open` call, but the primary path enforces the most restrictive permissions possible.

## Secure Load and Save Lifecycle

The configuration lifecycle ensures all modifications traverse the security-checked pathway. On instantiation, the `Config` class loads existing data via `yaml.safe_load` in the `load` method (lines 42-47).

The `save` routine always rewrites the entire file rather than appending, guaranteeing that every change persists through the permission-validated `os.open` call. This atomic replacement strategy prevents corruption and maintains the 600 permission invariant across updates.

## Programmatic Credential Access API

Agent Reach abstracts file handling behind a uniform API that prevents direct filesystem manipulation by callers:

- **`get(key, default)`** – Retrieves values from the in-memory dictionary, falling back to environment variables (checking `KEY.upper()`) if the key is absent from the file.
- **`set(key, value)`** – Updates the internal dictionary and immediately persists the change to disk through the secure save pathway.
- **`delete(key)`** – Removes a key from the configuration and triggers a save operation.

This design ensures that YAML remains the single source of truth while providing programmatic convenience for CLI tools and diagnostic utilities.

## Feature-Based Secret Validation

The `FEATURE_REQUIREMENTS` mapping (defined in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) lines 21-28) declares which credential keys are mandatory for optional integrations. For example, the Exa Search feature requires the `exa_api_key` secret to be present.

The `is_configured(feature)` method checks that all required keys for a given feature exist and are non-empty. This allows the CLI and `doctor` diagnostics to warn users when credentials are missing before attempting API calls that would fail authentication.

## Runtime Secret Masking

To prevent accidental credential leakage in logs or terminal output, the `to_dict` method (lines 102-108) implements intelligent value masking. When the configuration is displayed—such as during `agent_reach doctor` execution—the method scans for keys containing sensitive substrings including **"key"**, **"token"**, **"password"**, or **"proxy"**.

Matching values are replaced with a truncated placeholder like `abcd1234...`, providing visual confirmation that the credential is set while protecting the actual secret from exposure.

## Implementation Example

The following pattern demonstrates secure credential management using the Agent Reach Config API:

```python
from agent_reach.config import Config

# Initialise (creates ~/.agent-reach/config.yaml with 600 permissions if missing)

cfg = Config()

# Store a new API key (file is saved with restricted permissions)

cfg.set("exa_api_key", "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")

# Retrieve a key – prefers file value, falls back to EXA_API_KEY env var

my_key = cfg.get("exa_api_key")

# Check whether the Exa Search integration is properly configured

if cfg.is_configured("exa_search"):
    print("Exa Search ready!")
else:
    print("Missing Exa API key in config or environment.")

# Display configuration without leaking secrets in logs

print(cfg.to_dict())

```

## Summary

- **Agent Reach stores credentials in `~/.agent-reach/config.yaml` with 600 permissions**, ensuring only the owning user can access the file.
- **The `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) handles secure file creation via `os.open`**, preventing world-readable credential exposure during write operations.
- **All credential access flows through `get`, `set`, and `delete` methods**, abstracting direct file manipulation while maintaining YAML as the authoritative source.
- **The `is_configured` method validates feature requirements**, checking for mandatory API keys before executing integration-specific code.
- **The `to_dict` method masks sensitive values** containing "key", "token", "password", or "proxy" to prevent accidental leaks in CLI output.

## Frequently Asked Questions

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

Agent Reach stores all user-specific credentials in `~/.agent-reach/config.yaml` within the user's home directory. This path is managed by the `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py), which automatically creates the `.agent-reach` directory on first use to isolate configuration data from other files.

### What file permissions does Agent Reach use for config.yaml?

The configuration file is created with **600 permissions** (octal `0o600`), meaning only the file owner has read and write access. The `save` method in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) explicitly uses `os.open` with `stat.S_IRUSR | stat.S_IWUSR` to enforce this restriction at the filesystem level, eliminating windows where credentials might be accessible to other users.

### How does Agent Reach prevent secrets from appearing in logs or terminal output?

The `to_dict` method (lines 102-108 of [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)) automatically masks sensitive configuration values. When converting the configuration to a dictionary for display—such as when running `agent_reach doctor`—the method detects keys containing "key", "token", "password", or "proxy" and replaces their values with truncated placeholders like `abcd1234...`.

### Can Agent Reach read credentials from environment variables?

Yes. The `get(key, default)` method checks for environment variables as a fallback mechanism. Specifically, it looks for an environment variable named `KEY.upper()` before returning the default value. This allows users to override file-based configuration with environment-level secrets when preferred for containerized deployments or CI/CD pipelines.