Agent Reach Credential Storage Security in config.yaml: A Technical Deep Dive
Agent Reach stores API keys and secrets in ~/.agent-reach/config.yaml with strict 0o600 file permissions and automatic masking to prevent credential leakage.
The Panniantong/Agent-Reach repository implements a defense-in-depth strategy for Agent Reach credential storage security by combining filesystem permissions, secure file handling, and runtime masking. Rather than scattering secrets across environment variables or plaintext files, the tool centralizes configuration in a single YAML file protected by Unix-style access controls and programmatic safeguards.
Config File Location and Directory Isolation
Agent Reach creates a dedicated configuration directory in the user's home folder to isolate sensitive data from other applications. According to the source code in agent_reach/config.py, the Config class initializes with a hardcoded path:
# From agent_reach/config.py lines 18-20
self.config_dir = Path.home() / ".agent-reach"
self.config_file = self.config_dir / "config.yaml"
The _ensure_dir method automatically creates this hidden directory on first use. By confining all settings—including API keys for integrations like Exa Search—to ~/.agent-reach/, the tool prevents accidental exposure through generic backup scripts or directory listings.
Permission-Based Security Model
Restricted File Permissions (0o600)
When persisting credentials, Agent Reach opens the YAML file using low-level os.open calls with explicit permission flags. The save method in agent_reach/config.py (lines 52-60) enforces owner-only access:
import os
import stat
# Create file with restrictive permissions atomically
fd = os.open(
self.config_file,
os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
stat.S_IRUSR | stat.S_IWUSR # 0o600: read/write for owner only
)
This approach eliminates race conditions where the file might temporarily be world-readable during creation. On platforms where os.open flags are unsupported (e.g., Windows), the code falls back to standard open() calls, but the primary path ensures credentials are never accessible to other users on the system.
Atomic Write Operations
The save method rewrites the entire configuration file for every modification, ensuring that permission checks run consistently. This explicit load-and-save cycle guarantees that any change to the config.yaml structure goes through the secure pathway defined in the core configuration logic.
Configuration API and Secure Access Patterns
Explicit Load and Save Cycle
Upon instantiation, the Config class loads existing data using yaml.safe_load (lines 42-47 in agent_reach/config.py), preventing arbitrary code execution during YAML parsing. The API abstracts file handling through three primary methods:
get(key, default): Retrieves values from an in-memory dictionary, falling back to environment variables (matchingKEY.upper()) if the key is absent from the fileset(key, value): Updates the dictionary and immediately persists to disk with 0o600 permissionsdelete(key): Removes the entry and rewrites the file securely
Feature-Based Requirement Checks
The FEATURE_REQUIREMENTS mapping (lines 21-28) defines which credential sets are mandatory for optional integrations. For example, the Exa Search feature requires exa_api_key. The is_configured(feature) method validates that all required secrets exist before allowing the CLI to execute integration-specific commands:
from agent_reach.config import Config
cfg = Config()
# Check if Exa Search integration is ready
if cfg.is_configured("exa_search"):
# Safe to use Exa API
pass
else:
print("Missing Exa API key in config.yaml")
Sensitive Data Masking and Display Protection
To prevent credential leakage in logs or terminal output, the to_dict method (lines 102-108) implements automatic masking. When displaying configuration data—for example, during agent_reach doctor diagnostics—the method replaces any value whose key contains sensitive substrings with a truncated placeholder:
Masked key patterns:
keytokenpasswordproxy
Values matching these patterns appear as abcd1234... rather than the actual secret, allowing users to verify that credentials are set without exposing the raw strings.
Practical Implementation Examples
The following pattern demonstrates secure credential management according to the agent_reach/config.py implementation:
from agent_reach.config import Config
# Initialize (creates ~/.agent-reach/ with proper permissions if missing)
cfg = Config()
# Store API key (automatically saves with 0o600 permissions)
cfg.set("exa_api_key", "sk-live-xxxxxxxxxxxxxxxx")
# Retrieve with environment fallback
# Checks config.yaml first, then EXA_API_KEY env var
api_key = cfg.get("exa_api_key")
# Validate feature readiness before API calls
if cfg.is_configured("exa_search"):
print("Exa Search ready")
else:
raise ValueError("Configure exa_api_key first")
# Display-safe output (shows abcd1234... instead of real key)
safe_config = cfg.to_dict()
Summary
- Agent Reach stores credentials in
~/.agent-reach/config.yamlwith 0o600 permissions enforced viaos.openandstat.S_IRUSR | stat.S_IWUSR. - The Config class in
agent_reach/config.pyprovides atomic write operations, environment variable fallback, and feature-based requirement validation. - Sensitive value masking automatically protects keys containing "token", "key", "password", or "proxy" from appearing in diagnostic output.
- The isolation of configuration to a dedicated hidden directory prevents accidental inclusion in backups or version control.
Frequently Asked Questions
Where does Agent Reach store the config.yaml file?
Agent Reach stores the configuration file at ~/.agent-reach/config.yaml in the user's home directory. The Config class automatically creates this path during initialization using Path.home() / ".agent-reach", ensuring consistent location across all platforms while keeping the directory hidden from standard directory listings.
What file permissions does Agent Reach use for credential storage?
The repository uses stat.S_IRUSR | stat.S_IWUSR (octal 0o600) when creating the YAML file, meaning only the file owner can read or write the contents. The save method in agent_reach/config.py uses os.open with these flags to set permissions atomically at creation time, preventing the file from ever being world-readable.
How does Agent Reach prevent credentials from appearing in logs?
When the to_dict method generates output for display (such as during agent_reach doctor), it checks if keys contain sensitive substrings like "key", "token", "password", or "proxy". Matching values are replaced with the masked placeholder abcd1234..., ensuring that diagnostic output and logging frameworks cannot capture the actual secrets.
Can Agent Reach read credentials from environment variables?
Yes. The get method first checks the in-memory configuration dictionary, then falls back to environment variables using the uppercase version of the key (e.g., EXA_API_KEY for exa_api_key). This allows temporary overrides without modifying the filesystem-stored config.yaml, while the file remains the authoritative source of truth.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →