Severity: P3
Summary
While apc collect correctly redacts secrets from the APC cache and stores them in the OS keychain, apc mcp sync resolves those secrets and writes them back to disk in plaintext inside tool-specific config files (e.g. ~/.claude.json, ~/.cursor/mcp.json). This is functionally necessary, but the security implication is undocumented and may surprise users.
Affected Code
src/appliers/claude.py — apply_mcp_servers():
env = server.get("env", {}).copy()
for key, value in env.items():
if isinstance(value, str) and value.startswith("${"):
secret_name = value[2:-1]
if secret_name in secrets:
env[key] = secrets[secret_name] # plaintext secret injected
mcp_servers[name] = { ... "env": env } # written to ~/.claude.json
_claude_json().write_text(json.dumps(data, indent=2), ...)
Security Model Gap
| Stage |
Secret state |
apc collect |
Redacted to ${PLACEHOLDER} in APC cache; stored in OS keychain |
apc mcp sync |
Resolved from keychain → written in plaintext to tool config |
apc export |
Read from keychain → age-encrypted in export archive |
The keychain protection is bypassed after every sync. If the tool's config file is:
- Included in a git commit by accident
- Readable by other processes/users
- Backed up to iCloud/Dropbox without encryption
...the secrets are exposed.
Recommended Mitigations
- Document this behavior clearly in
apc mcp sync help text and README
- Warn the user during sync that secrets will be written plaintext:
⚠ Resolving 3 secrets from keychain → writing to ~/.claude.json (plaintext)
- Long-term: Explore if tools support referencing environment variables so secrets stay out of config files entirely
- Add a note to the export command that the export encrypts secrets, but the on-disk tool configs do not
References
- CWE-312: Cleartext Storage of Sensitive Information
Severity: P3
Summary
While
apc collectcorrectly redacts secrets from the APC cache and stores them in the OS keychain,apc mcp syncresolves those secrets and writes them back to disk in plaintext inside tool-specific config files (e.g.~/.claude.json,~/.cursor/mcp.json). This is functionally necessary, but the security implication is undocumented and may surprise users.Affected Code
src/appliers/claude.py — apply_mcp_servers():Security Model Gap
apc collect${PLACEHOLDER}in APC cache; stored in OS keychainapc mcp syncapc exportThe keychain protection is bypassed after every sync. If the tool's config file is:
...the secrets are exposed.
Recommended Mitigations
apc mcp synchelp text and READMEReferences