Security Implications of Storing API Keys in CodexBar: Risks and Mitigations
CodexBar stores LLM provider API keys as plain-text strings in memory after reading them from environment variables or unencrypted JSON configuration files, exposing them to disk leakage, subprocess environment inheritance, and potential memory extraction.
CodexBar is an open-source macOS menu bar application that integrates multiple LLM providers into a unified interface. Understanding the security implications of storing API keys in CodexBar is critical for developers, as the application implements a token-driven architecture that persists credentials in readable formats and inherits standard process security limitations.
How CodexBar Reads and Stores API Keys
The token resolution system centers around SettingsReader structs and the ProviderTokenResolver class. According to the steipete/CodexBar source code, credentials are sourced from three distinct locations:
-
Environment variables – Each provider defines specific keys such as
OPENAI_API_KEYorVENICE_API_KEYinOpenAIAPISettingsReader.swift(lines 3-10) andVeniceSettingsReader.swift(lines 4-10), accessed via the staticapiKey(environment:)method. -
User-wide configuration – The
~/.codexbar/config.jsonfile is parsed at application startup byCLIDiagnoseCommand.swift(line 265), with values falling back to the same environment helper methods. -
Provider-specific overrides – Files such as
.codexbar/provider-config.jsonare merged into the environment dictionary before anySettingsReaderis consulted.
The ProviderTokenResolver (lines 190-260) then determines which token takes precedence for each request, storing the final value as a standard Swift String in process memory.
Critical Security Vulnerabilities
Plain-Text Storage on Disk
The JSON configuration file is written without encryption. If the user's home directory backs up to cloud services, API keys travel with the backup unencrypted. Additionally, any process running under the user's UID can read ~/.codexbar/config.json, enabling malicious scripts to exfiltrate credentials directly from the filesystem.
Environment Variable Leakage
When CodexBar spawns subprocesses, the full environment is inherited by default. Child processes that log their environment or crash and write core dumps may expose keys. While UsageStore+APIKeyDebug.swift (line 19) implements scrubbing logic to remove sensitive values from diagnostics, developers must ensure all diagnostic paths honor this scrubbing to prevent accidental leakage.
In-Process Memory Exposure
Tokens are stored as plain Swift String instances in heap memory. A memory dump or debugger attached to the running app can read these values directly. CodexBar does not currently use the macOS Secure Enclave, Keychain services, or secure memory buffers for transient storage, leaving keys vulnerable to extraction via memory inspection tools.
Provider Host Validation Risks
While tokens are only transmitted after host validation (implemented in ZaiProviderDescriptor.swift, lines 36-40), a compromised configuration could redirect a provider to an attacker-controlled endpoint. In this scenario, the API key would be leaked in the HTTP Authorization header despite the validation checks, as the token is sent after the connection is established.
Accidental Version Control Exposure
Running git add . from the project root could stage configuration files containing keys. Although the repository includes a .gitignore entry for *.json, manually created files or override configs might bypass this protection, risking credential exposure in public repositories.
Mitigation Strategies for Secure Token Management
To reduce the attack surface while using CodexBar, implement the following defensive measures:
-
Prefer environment variables over config files for CI/CD or shared machines. The
SettingsReaderimplementation already prioritizes environment variables; avoid persisting credentials to disk where possible. -
Restrict file permissions by running
chmod 600 ~/.codexbar/config.jsonto limit read access to the file owner only. -
Filter subprocess environments before spawning child processes. Remove
*_API_KEYentries that are not required, referencing the scrubbing map defined inTokenAccountSupportCatalog+Data.swift. -
Validate provider URLs rigorously. Keep the host-validation logic in provider descriptors updated and consider implementing DNS pinning to prevent redirection attacks.
-
Implement CI checks that forbid committing files matching
*.jsoncontainingAPI_KEYpatterns to prevent accidental credential leakage.
Secure Implementation Examples
The following Swift patterns demonstrate safer handling of credentials within the CodexBar ecosystem:
// Reading OpenAI key from environment with validation
let openAIKey = OpenAIAPISettingsReader.apiKey(environment: ProcessInfo.processInfo.environment)
guard let apiKey = openAIKey, !apiKey.isEmpty else {
fatalError("OpenAI API key not set – export OPENAI_API_KEY or place it in ~/.codexbar/config.json")
}
// Spawning subprocess without leaking other provider keys
var safeEnv = ProcessInfo.processInfo.environment
safeEnv.removeValue(forKey: "ANOTHER_PROVIDER_API_KEY")
let task = Process()
task.environment = safeEnv
task.executableURL = URL(fileURLWithPath: "/usr/bin/curl")
task.arguments = ["-H", "Authorization: Bearer \(apiKey)", "https://api.openai.com/v1/models"]
try task.run()
Summary
- CodexBar reads API keys from environment variables or unencrypted
~/.codexbar/config.jsonfiles, storing them as plain-text strings in memory. - Plain-text storage exposes keys to backup services and other user processes with filesystem access.
- Environment inheritance risks leaking keys to child processes and crash dumps unless explicitly scrubbed.
- Memory exposure allows debuggers to extract tokens since they are not stored in Secure Enclave or secure buffers.
- Mitigation requires preferring environment variables, restricting file permissions to
600, filtering subprocess environments, and implementing CI checks to prevent accidental commits.
Frequently Asked Questions
Does CodexBar encrypt API keys stored in the config file?
No. According to the source code in CLIDiagnoseCommand.swift (line 265), the ~/.codexbar/config.json file is written and read as unencrypted plain text. The application does not currently implement encryption at rest for configuration files. You should mitigate this by restricting file permissions to 600 and preferring environment variables for sensitive credentials.
How does CodexBar prevent API keys from appearing in logs?
The codebase includes specific scrubbing logic in UsageStore+APIKeyDebug.swift (line 19) and TokenAccountSupportCatalog+Data.swift that identifies environment variables matching *_API_KEY patterns and replaces their values with redacted placeholders in diagnostic output. However, this scrubbing must be manually applied to all logging paths to ensure complete coverage, as not all diagnostic commands automatically inherit the scrubbing map.
Can API keys be extracted from CodexBar's memory while it is running?
Yes. CodexBar stores tokens as standard Swift String instances in process memory. Without using the macOS Secure Enclave or Keychain for transient storage, these values are vulnerable to memory dumps and debugger attachment. There is currently no functionality to zero out strings after use, though wrapping tokens in a custom type that overwrites its buffer on deinitialization could reduce exposure.
What happens if a malicious provider URL is configured in CodexBar?
The ProviderTokenResolver validates hosts before sending tokens, as implemented in ZaiProviderDescriptor.swift (lines 36-40). However, if an attacker compromises the configuration to point to an attacker-controlled endpoint, the API key will be transmitted in the HTTP Authorization header to that malicious server. Always validate provider URLs manually and use DNS pinning where possible to prevent this redirection attack.
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 →