How Agent Reach Handles Secure Storage of Credentials and File Permissions
Agent Reach stores all API keys, tokens, and secrets in ~/.agent-reach/config.yaml with strict 0o600 file permissions, masks sensitive values in diagnostic output, and optionally falls back to environment variables to prevent accidental credential exposure.
Agent Reach is an open-source automation framework that manages sensitive credentials for various APIs and services. The project implements a defense-in-depth approach to credential security through the Config class in agent_reach/config.py, which centralizes all read and write operations to a single, protected YAML file in the user's home directory.
Secure Storage Architecture
The credential storage system relies on a singleton YAML file located at ~/.agent-reach/config.yaml. This design consolidates all secrets into one location where strict permissions can be enforced.
File Permissions and Creation Flags
When writing the configuration file, the Config class uses low-level operating system flags to prevent unauthorized access. In agent_reach/config.py, the save() method opens the file with os.open(..., stat.S_IRUSR | stat.S_IWUSR), which corresponds to mode 0o600 (read/write for owner only).
If the low-level os.open flags are unavailable—such as on Windows—the code falls back to a standard open() call, but the directory creation via mkdir(parents=True, exist_ok=True) still minimizes exposure by ensuring the path exists before any write operation.
Directory Structure and Initialization
The _ensure_dir() method creates the ~/.agent-reach directory on first use. This guarantees that the parent directory exists before any credential writes, preventing race conditions or permission inheritance issues from temporary directories.
Security Mechanisms in the Config Class
The Config class implements multiple layers of protection beyond file permissions to prevent accidental credential leakage.
Environment Variable Fallback
The Config.get() method checks the YAML configuration file first, then falls back to environment variables using os.environ.get(key.upper()). This allows users to keep sensitive values out of the filesystem entirely by exporting them as environment variables, reducing the risk of file-based credential exposure.
Sensitive Value Masking
When displaying configuration data, Config.to_dict() automatically masks values for any key containing "key", "token", "password", or "proxy". These values are truncated to the first eight characters followed by an ellipsis (e.g., abcd1234...), ensuring that diagnostic output or logs never reveal full secrets.
Centralized Write Path
All CLI commands and helper functions store credentials through Config.set(). This guarantees that every write operation passes through the same permission-controlled routine in Config.save(), preventing third-party code from bypassing security measures and writing credentials with world-readable permissions.
Third-Party Tool Integration
Agent Reach synchronizes credentials with auxiliary tools while maintaining consistent security standards.
Legacy Credential Sync
When importing Twitter cookies, the helper functions in agent_reach/cookie_extract.py write the same secrets to ~/.config/xfetch/session.json and ~/.config/bird/credentials.env. These auxiliary files are also created with mode 0o600, ensuring that credentials remain protected even when shared with external tools.
Practical Implementation Examples
Setting Credentials via CLI
Use the configure command to store credentials securely:
# Set a GitHub token
agent-reach configure github-token ghp_XXXXXXXXXXXXXXXXXXXX
Behind the scenes, the CLI parses the input and calls config.set("github_token", value), which triggers the save() routine with 0o600 permissions.
Programmatic Credential Management
from agent_reach.config import Config
cfg = Config() # Loads ~/.agent-reach/config.yaml
cfg.set("exa_api_key", "sk-abc123") # Saves with secure permissions
print(cfg.to_dict()) # Output: {'exa_api_key': 'sk-abc12...'}
Reading with Environment Fallback
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
Verifying File Permissions
Confirm that credentials are protected at the filesystem level:
$ ls -l ~/.agent-reach/config.yaml
-rw------- 1 user user 1234 Jun 6 12:34 /home/user/.agent-reach/config.yaml
The -rw------- mode confirms that only the file owner can read or write the configuration.
Summary
- Agent Reach stores all credentials in ~/.agent-reach/config.yaml with strict 0o600 permissions enforced via
os.open()flags inagent_reach/config.py. - The Config class masks sensitive values containing "key", "token", "password", or "proxy" when displaying configuration via
to_dict(). - Environment variable fallback in
Config.get()allows users to keep secrets out of the filesystem entirely. - Centralized writes through Config.set() ensure that all credentials pass through the same permission-controlled save routine.
- Legacy sync in cookie_extract.py extends 0o600 permissions to auxiliary files like
~/.config/xfetch/session.json.
Frequently Asked Questions
What file permissions does Agent Reach use for credential storage?
Agent Reach creates the ~/.agent-reach/config.yaml file with mode 0o600 (read/write for owner only) using os.open() with stat.S_IRUSR | stat.S_IWUSR flags. This prevents other users on the system from accessing API keys, tokens, or passwords stored in the file.
How does Agent Reach prevent credentials from appearing in logs?
The Config.to_dict() method in agent_reach/config.py automatically masks any value where the key contains "key", "token", "password", or "proxy". It displays only the first eight characters followed by an ellipsis (e.g., abcd1234...), ensuring that diagnostic output and logs never expose complete secrets.
Can I use environment variables instead of the config file?
Yes. The Config.get() method checks the YAML file first, then falls back to environment variables using os.environ.get(key.upper()). If you set EXA_API_KEY in your environment, cfg.get("exa_api_key") will return that value without reading from the config file, allowing you to keep credentials out of persistent storage.
Does Agent Reach protect credentials when syncing with third-party tools?
Yes. When the cookie_extract.py module syncs Twitter credentials to auxiliary files like ~/.config/xfetch/session.json or ~/.config/bird/credentials.env, it explicitly sets file mode 0o600 on these files as well, maintaining consistent security standards across all credential storage locations.
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 →