# Security Best Practices for Storing Cookies and API Keys in config.yaml

> Learn security best practices for storing cookies and API keys in config.yaml. Agent-Reach secures credentials using file permissions, log masking, and environment variable fallbacks.

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

---

**Agent-Reach stores sensitive credentials in `~/.agent-reach/config.yaml` with 600 permissions, masks secrets in logs, and falls back to environment variables to keep API keys and browser cookies secure.**

Agent-Reach is an open-source automation framework that manages user-specific secrets through a centralized YAML configuration. Understanding how to securely store cookies and API keys in config.yaml is essential to prevent credential leakage and unauthorized access. The repository implements several defensive patterns in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) that you should follow when handling sensitive data.

## Store Secrets in a Private User Directory

The `Config` class isolates sensitive data by storing the [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml) file inside a hidden directory under the user's home folder. According to the source code in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) (line 18), `Config.CONFIG_DIR` points to `Path.home() / ".agent-reach"`, ensuring that credentials are never stored in the project repository or shared locations.

This design prevents accidental commits to version control. You should ensure that `~/.agent-reach/config.yaml` remains excluded from any Git tracking and resides only in the current user's home directory.

## Create the File with Restrictive Permissions

When saving configuration data, the `Config.save()` method enforces strict file permissions using low-level OS flags. As implemented in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) (lines 49-60), the method opens the file with `os.O_WRONLY | os.O_CREAT | os.O_TRUNC` and applies mode `stat.S_IRUSR | stat.S_IWUSR` (octal `0o600`), granting read and write access exclusively to the file owner.

```python
from agent_reach.config import Config

cfg = Config()
cfg.set("openai_api_key", "sk-...")

```

On Unix systems, verify the permissions manually:

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

```

The code includes an `OSError` fallback (lines 64-67) for Windows environments where `os.open` flags are not fully supported. On Windows, manually restrict access using ACLs:

```bash
icacls ~/.agent-reach/config.yaml /grant %USERNAME%:R

```

## Never Log or Print Raw Secrets

The `Config` class prevents accidental secret exposure through the `to_dict()` method. Before returning configuration data, it masks any key containing "key", "token", "password", or "proxy" by truncating the value and appending an ellipsis, as implemented in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) (lines 101-110).

Always use `to_dict()` for debugging output instead of accessing `config.data` directly:

```python

# Safe: masks sensitive values

print(cfg.to_dict())

# Unsafe: exposes raw credentials

print(cfg.data)

```

## Prefer Environment Variables as a Fallback

The `Config.get()` method implements a secure fallback chain that prioritizes the YAML file but automatically checks environment variables. As shown in lines 70-78 of [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py), the method first attempts to retrieve the key from the config, then falls back to `os.environ.get(key.upper())`.

This pattern allows you to store short-lived secrets in environment variables while maintaining persistent configuration in the YAML file:

```bash
export OPENAI_API_KEY="sk-..."

```

```python

# Checks config.yaml first, then $OPENAI_API_KEY

api_key = cfg.get("openai_api_key")

```

## Validate Required Keys Per Feature

Before enabling functionality that requires credentials, use the `is_configured()` method to verify that all necessary secrets exist. The `FEATURE_REQUIREMENTS` dictionary (lines 22-28 in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)) maps each feature to its required configuration keys.

This validation prevents runtime errors and ensures that sensitive operations only execute when properly authenticated:

```python
if cfg.is_configured("twitter"):
    # Safe to proceed with Twitter automation

    pass

```

## Separate Cookie Handling from Generic Storage

Browser cookies receive special handling in [`agent_reach/cookie_extract.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cookie_extract.py). The `configure_from_browser` function (lines 260-284) writes cookie strings to dedicated keys such as `xhs_cookie`, `xueqiu_cookie`, or `twitter_cookies`, keeping them isolated from other configuration entries.

When using the CLI to store cookies, the input is parsed but never logged in full. The `cli._parse_twitter_cookie_input` method (lines 51-58) only reports the count of extracted cookies rather than the raw content, preventing credential leakage in shell history or log files.

```bash

# Stores cookies without echoing values to stdout

agent-reach configure twitter-cookies "auth_token=AAA; ct0=BBB"

```

## Summary

- **Isolate credentials**: Store [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml) in `~/.agent-reach/` outside version control.
- **Restrict permissions**: The `Config.save()` method automatically applies `0o600` permissions; manually verify with `chmod 600` on Unix.
- **Mask secrets**: Use `Config.to_dict()` to safely display configuration without exposing API keys or passwords.
- **Use environment fallbacks**: Leverage `Config.get()` to check environment variables when YAML values are missing.
- **Validate requirements**: Call `is_configured()` before accessing features that depend on sensitive keys.
- **Isolate cookies**: Store browser cookies in dedicated keys and avoid logging raw cookie strings.

## Frequently Asked Questions

### How does Agent-Reach protect against accidental credential commits?

The framework stores all secrets in `~/.agent-reach/config.yaml` within the user's home directory, not the project repository. This path is defined in `Config.CONFIG_DIR` ([`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) line 18) and automatically created at runtime, ensuring sensitive files never reside in Git-tracked directories.

### What permissions should the config.yaml file have?

The file should have `600` (octal `0o600`) permissions, meaning only the owner can read and write. The `Config.save()` method enforces this by opening the file with `os.O_WRONLY | os.O_CREAT` and `stat.S_IRUSR | stat.S_IWUSR` flags. On Windows, you should manually set ACLs to restrict access to the current user.

### How can I safely display configuration values for debugging?

Call `Config.to_dict()` rather than accessing the raw data dictionary. This method automatically masks values for keys containing "key", "token", "password", or "proxy", preventing secret leakage in logs or console output.

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

Yes. The `Config.get()` method checks the YAML file first, then falls back to an uppercase environment variable (e.g., `OPENAI_API_KEY`). This allows temporary overrides without modifying the persistent configuration file, useful for CI/CD pipelines or shared environments.