How Plaintext Credential Storage Happens in JSON Configuration Files and How to Fix It
The Problem in Plain Sight
Configuration files are often the most overlooked attack surface in a codebase. They sit quietly in the repository, rarely reviewed in security audits, yet they can hold some of the most sensitive data in your application. In this case, assets/settings/global.json did exactly that — it stored a real phone number in the dono1 field and established a placeholder pattern for API keys that practically invited developers to commit real credentials to version control.
This post breaks down exactly what went wrong, why it matters, and what the fix looks like — with concrete code references from the actual pull request.
Introduction
The assets/settings/global.json file serves as a central configuration store for the application, holding everything from API keys (including a Gemini API key field, API_KEY_GEMINI) to owner contact numbers (dono1 through dono4). While most fields used placeholder strings like _COLE_SUA_KEY_AQUI_ ("put your key here" in Portuguese), the dono1 field at line 19 contained a real, live phone number: 559284818701.
This is a textbook example of PII (Personally Identifiable Information) exposure — a real phone number, likely a Brazilian mobile number based on the 55 country code and 92 area code prefix, committed directly into a production codebase.
Beyond the PII issue, the broader design pattern is dangerous: the file's placeholder convention (_COLE_SUA_KEY_AQUI_) is a ticking time bomb. Any developer following the pattern will substitute real API keys and credentials directly into this file — a file that lives in version control, gets cloned by every contributor, and may be accessible on the production filesystem.
The Vulnerability Explained
What Was in the File
Here is the relevant section of assets/settings/global.json before the fix:
{
"API_KEY_GEMINI": "_COLE_SUA_KEY_AQUI_",
"listanegra_global": [],
"blockcmd_global": [],
"dono1": "559284818701",
"dono2": "...",
"dono3": "...",
"dono4": "..."
}
Two distinct problems exist here:
-
Hardcoded PII: The value
559284818701is a real phone number stored in thedono1field. This is PII under GDPR, LGPD (Brazil's data protection law), and most other privacy frameworks. -
Dangerous placeholder pattern: Fields like
API_KEY_GEMINIuse Portuguese-language placeholders (_COLE_SUA_KEY_AQUI_= "put your key here"). This is an implicit instruction to developers to replace these values with real credentials — in the same file — which will then be committed to version control.
Why This Is Exploitable
The exploitation scenario is straightforward and requires no sophisticated tooling:
-
Repository exposure: If the repository is public, or if an attacker gains read access to a private repository (via a leaked token, insider threat, or misconfigured CI/CD system), they can clone the repo and read
assets/settings/global.jsondirectly. Any real credentials substituted for the placeholders are immediately exposed. -
Filesystem access: On a deployed server, if an attacker achieves path traversal (e.g., via a misconfigured web server or a directory traversal vulnerability in the Node.js application), they can read the JSON file and extract all credentials in cleartext.
-
PII harvesting: The phone number in
dono1can be harvested for spam, phishing, or social engineering attacks against the owner of that number. -
Downstream consumer risk: This is described as a Node.js library. Every downstream project that installs this package and follows the placeholder substitution pattern will inherit the same vulnerability in their own deployments.
The vulnerability is classified under CWE-312: Cleartext Storage of Sensitive Information — the system stores sensitive data (PII and potentially API keys) without any cryptographic protection, making it trivially readable by anyone with file or repository access.
Notably, the PR description also mentions that PBKDF2 is available in the Rust dependencies (src-tauri/Cargo.lock:3809) and that getToken/setToken functions in plugins/auth-oauth2/src/store.ts write credentials to disk without encryption — a related but separate issue that reinforces the pattern of insecure credential handling across this codebase.
The Fix
What Changed
The fix is surgical and targeted. A single line in assets/settings/global.json was changed:
Before:
"dono1": "559284818701",
After:
"dono1": "_SEU_NUMERO_AQUI_",
The real phone number 559284818701 is replaced with the placeholder _SEU_NUMERO_AQUI_ ("your number here" in Portuguese), consistent with the placeholder convention used by other fields in the file.
Why This Matters
This change accomplishes two things immediately:
-
Removes PII from version control: The real phone number is no longer in the git history going forward. (Note: a full remediation should also include a
git historyrewrite or at minimum a warning that the number exists in prior commits.) -
Reinforces the placeholder pattern as the correct baseline: By ensuring all sensitive fields use placeholder values in the committed file, the repository no longer contains any real sensitive data by default. Developers are reminded to substitute values locally, not in the committed file.
What the Fix Does NOT Do (And What Else You Should Do)
The placeholder fix is a necessary first step, but it does not fully solve the underlying design problem. The placeholder pattern itself is inherently risky because it relies on developer discipline. A more robust solution involves:
- Environment variables: Load sensitive values like
API_KEY_GEMINIand owner phone numbers from environment variables (process.env.API_KEY_GEMINI) rather than from a JSON file. - Secrets manager integration: Use a service like AWS Secrets Manager, HashiCorp Vault, or Doppler to inject credentials at runtime without ever writing them to disk or to version control.
.gitignorefor local overrides: Provide aglobal.json.examplewith placeholders (committed), and instruct developers to create a localglobal.json(gitignored) with real values.
Prevention & Best Practices
Never Commit Real Credentials or PII
This sounds obvious, but the dono1 field shows how easy it is to slip a real value into a config file. Establish a pre-commit hook using a tool like git-secrets or truffleHog to scan for phone numbers, API key patterns, and other sensitive data before they reach the repository.
Use Environment Variables for Runtime Secrets
Instead of:
{
"API_KEY_GEMINI": "_COLE_SUA_KEY_AQUI_"
}
Do this in your Node.js code:
const apiKeyGemini = process.env.API_KEY_GEMINI;
if (!apiKeyGemini) {
throw new Error('API_KEY_GEMINI environment variable is not set');
}
This ensures the key is never written to any file in the repository.
Encrypt Credentials at Rest
As noted in the vulnerability description, PBKDF2 is already available in the Tauri Rust dependencies. For credentials that must be stored on disk (e.g., OAuth tokens via plugins/auth-oauth2/src/store.ts), use PBKDF2 or a similar KDF to derive an encryption key from a device-specific secret, then encrypt the credential before writing it to disk.
Rotate Exposed Credentials Immediately
If a real API key or phone number was ever substituted into global.json and committed, treat it as compromised. Rotate the API key immediately and notify the individual whose phone number was exposed.
Apply Principle of Least Privilege to Config Files
Ensure that assets/settings/global.json (and any local override containing real values) has filesystem permissions that restrict read access to the application process only. On Linux/macOS: chmod 600 global.json.
Relevant Standards
- CWE-312: Cleartext Storage of Sensitive Information
- OWASP A02:2021 – Cryptographic Failures: Covers failure to protect sensitive data at rest
- OWASP Secrets Management Cheat Sheet: Guidance on handling secrets in applications
Key Takeaways
- The
dono1field inglobal.jsoncontained a real Brazilian phone number — a direct PII violation that required immediate removal from the codebase and its git history. - The
_COLE_SUA_KEY_AQUI_placeholder pattern is dangerous by design: it instructs developers to write real credentials into a version-controlled file, making credential exposure a matter of when, not if. - JSON configuration files committed to version control should never contain real credentials or PII — not even temporarily, because git history is permanent.
- The presence of PBKDF2 in
src-tauri/Cargo.lockbut its absence inplugins/auth-oauth2/src/store.tshighlights a broader pattern of available-but-unused cryptographic tooling in this codebase. - Downstream consumers of this Node.js library inherit the risk: any project following the placeholder substitution pattern will expose their own credentials in the same way.
How Orbis AppSec Detected This
- Source: The
dono1field at line 19 ofassets/settings/global.json, where a real phone number (559284818701) was stored as a literal string value in a version-controlled production configuration file. - Sink: Any filesystem read of
assets/settings/global.json— whether via direct repository access, a cloned copy, or a path traversal exploit against the deployed application. - Missing control: No secrets scanning pre-commit hook, no environment variable injection pattern, no encryption of sensitive fields, and no
.gitignorerule to prevent the file with real values from being committed. - CWE: CWE-312 — Cleartext Storage of Sensitive Information.
- Fix: The hardcoded phone number
559284818701in thedono1field was replaced with the placeholder_SEU_NUMERO_AQUI_, removing PII from the repository and reinforcing the safe placeholder baseline.
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
The vulnerability in assets/settings/global.json is a reminder that configuration files are code — they deserve the same scrutiny as any .ts or .js file in your project. A single hardcoded phone number and a well-intentioned placeholder pattern created a setup where real PII and API credentials were one developer substitution away from living permanently in version control.
The fix is simple: replace real values with placeholders, move secrets to environment variables, and add pre-commit scanning to catch anything that slips through. For credentials that must be stored on disk, leverage the cryptographic libraries already in your dependency tree — PBKDF2 is right there in Cargo.lock, waiting to be used.
Security in configuration management is not glamorous, but it is foundational. The most sophisticated encryption in your application means nothing if the API keys are sitting in a JSON file on GitHub.
References
- CWE-312: Cleartext Storage of Sensitive Information
- OWASP Secrets Management Cheat Sheet
- OWASP Top 10 A02:2021 – Cryptographic Failures
- Semgrep rules for hardcoded secrets
- truffleHog: Secrets scanning for git repositories
- git-secrets: Prevents committing secrets to git
- fix: configuration file contains placeholder values ... in global.json