Security Considerations for Agent-Reach Config File Permissions: A Complete Guide
Agent-Reach enforces strict filesystem permissions (directory mode 0o700 and file mode 0o600) on its configuration files to protect sensitive credentials like API keys and tokens from unauthorized access.
The Agent-Reach library stores user-specific authentication data in ~/.agent-reach/config.yaml, requiring robust security measures to prevent credential leakage. Understanding the security considerations for Agent-Reach config file permissions is essential for developers handling sensitive API keys, OAuth tokens, and browser cookies. The codebase implements defense-in-depth strategies spanning directory creation, file access controls, and runtime masking across both POSIX and Windows platforms.
Configuration File Location and Sensitivity
Agent-Reach persists configuration data in a YAML file located at ~/.agent-reach/config.yaml. This path resides within a hidden directory in the user's home folder, specifically designed to store high-sensitivity values including API keys, access tokens, and session cookies.
Because these credentials grant access to external services and user accounts, the library treats the configuration directory as a private vault. The implementation follows the principle of least privilege, ensuring that only the owning user account can read or modify these files.
Permission Enforcement Mechanisms
Agent-Reach implements multiple layers of filesystem protection during initialization and write operations. These mechanisms operate differently across platforms but maintain consistent security intent.
Private Directory Creation (0o700)
When the Config class initializes, it creates the configuration directory with restrictive permissions using the make_private_dir helper function. In agent_reach/utils/paths.py, this function explicitly sets directory mode to 0o700 (owner read/write/execute only) and applies os.chmod on non-Windows systems.
The initialization occurs in Config.__init__ at lines 33-36 of agent_reach/config.py:
from agent_reach.utils.paths import make_private_dir
class Config:
def __init__(self):
self.config_dir = Path.home() / ".agent-reach"
make_private_dir(self.config_dir) # Mode 0o700 enforced
This prevents other users from listing or accessing the directory contents, even if they have broader filesystem access.
Secure File Creation (0o600)
When writing configuration changes, Agent-Reach avoids race conditions by using os.open with atomic permission flags. The Config.save method at lines 54-62 of agent_reach/config.py opens the file with stat.S_IRUSR | stat.S_IWUSR (octal 0o600), ensuring the file is created with user-only read/write permissions:
import os
import stat
def save(self):
flags = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
mode = stat.S_IRUSR | stat.S_IWUSR # 0o600
fd = os.open(self.config_path, flags, mode)
with os.fdopen(fd, 'w') as f:
yaml.dump(self.data, f)
This approach eliminates the temporary window where a newly created file might inherit default permissions (potentially world-readable) before explicit restrictions are applied.
Cross-Platform Fallback Handling
On Windows or environments where os.open flags are unavailable, Agent-Reach implements a fallback mechanism. Lines 66-73 of agent_reach/config.py catch exceptions and use the standard open call followed by explicit os.chmod to force 0o600 permissions:
try:
# Primary atomic method
fd = os.open(self.config_path, flags, mode)
except (OSError, AttributeError):
# Fallback for Windows or restricted environments
with open(self.config_path, 'w') as f:
yaml.dump(self.data, f)
os.chmod(self.config_path, 0o600)
Note that on Windows, os.chmod is effectively a no-op for ACL-based permissions, so the code relies on the operating system's default file creation semantics while maintaining API compatibility.
Runtime Protection and Secret Masking
Beyond filesystem permissions, Agent-Reach protects against accidental credential exposure in logs and console output. The to_dict method (lines 108-127 of agent_reach/config.py) automatically masks sensitive values based on key name patterns.
The masking logic identifies keys containing substrings like "key", "token", "password", or "cookie", replacing their values with truncated placeholders:
def to_dict(self):
sensitive = ['key', 'token', 'password', 'cookie', 'secret']
result = {}
for k, v in self.data.items():
if any(marker in k.lower() for marker in sensitive):
result[k] = str(v)[:8] + '...' # Truncate after 8 chars
else:
result[k] = v
return result
This ensures that calling print(config.to_dict()) or logging the configuration object never exposes full credential values, even if the output is redirected to shared logs or bug reports.
Verification and Best Practices
You can verify these security measures on POSIX systems using standard command-line tools:
# Check directory permissions (should show drwx------)
ls -ld ~/.agent-reach
# Check file permissions (should show -rw-------)
ls -l ~/.agent-reach/config.yaml
Expected output:
drwx------ 2 user user 4096 Jan 15 09:00 /home/user/.agent-reach
-rw------- 1 user user 220 Jan 15 09:00 /home/user/.agent-reach/config.yaml
When implementing Agent-Reach in production environments:
- Avoid cloud syncing the
~/.agent-reachdirectory to prevent credential proliferation across devices - Audit umask settings to ensure system-wide defaults don't override these restrictions
- Use environment variables for credentials when feasible, as
Config.get()checks environment variables before falling back to the file - Regularly rotate API keys stored in the configuration file
Summary
- Agent-Reach stores sensitive data in
~/.agent-reach/config.yamland enforces directory permissions0o700viamake_private_dirinagent_reach/utils/paths.py - File creation uses atomic
os.openwithstat.S_IRUSR | stat.S_IWUSR(0o600) inConfig.saveto prevent race condition vulnerabilities - Windows fallback uses standard file operations with subsequent
os.chmodcalls, though Windows ACLs depend on OS defaults - Runtime masking via
to_dictprevents accidental credential leakage in logs by truncating values for keys matching sensitive patterns - Verification on POSIX systems shows
drwx------for the directory and-rw-------for the configuration file
Frequently Asked Questions
What permissions does Agent-Reach set on its configuration directory?
Agent-Reach creates the configuration directory at ~/.agent-reach with mode 0o700 (owner read, write, and execute only) through the make_private_dir function in agent_reach/utils/paths.py. This prevents other users from listing or accessing directory contents on POSIX systems.
How does Agent-Reach prevent temporary file exposure during writes?
The Config.save method in agent_reach/config.py uses os.open with the flags stat.S_IRUSR | stat.S_IWUSR (octal 0o600) to atomically create the file with restricted permissions. This eliminates the race window where a file might temporarily exist with default permissions before explicit restrictions are applied.
Does Agent-Reach protect credentials when printing configuration objects?
Yes, the to_dict method automatically masks values for keys containing "key", "token", "password", or "cookie", displaying only the first eight characters followed by ellipsis. This prevents accidental exposure of secrets in logs, stack traces, or debug output.
Are these security measures effective on Windows?
Partially. While the code attempts to set 0o600 permissions via os.chmod, Windows uses ACL-based security rather than POSIX modes, making os.chmod a no-op. On Windows, Agent-Reach relies on the operating system's default file creation semantics and the user's home directory protections, though the masking and directory creation logic still function correctly.
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 →