Mar 3, 2026·6 min read·2 visits
Running maintenance commands like `openclaw doctor` or `update` silently replaces secure environment variable placeholders (e.g., `${KEY}`) in your config file with the actual cleartext secret values, permanently writing them to disk.
A critical information disclosure vulnerability exists in the OpenClaw AI assistant's configuration management subsystem. When processing configuration files that utilize environment variable interpolation (e.g., `${API_KEY}`), certain write operations—such as updates or repairs—inadvertently resolve these references to their runtime values and persist the cleartext secrets back to the disk. This effectively converts ephemeral, secure configuration references into permanent, plaintext credentials stored within `openclaw.json`, significantly increasing the risk of accidental secret leakage via version control or backup mechanisms.
The OpenClaw personal AI assistant supports a security best practice known as configuration interpolation, allowing users to reference environment variables in their openclaw.json file using the syntax ${VAR_NAME}. This ensures that sensitive secrets, such as LLM provider API keys (OpenAI, Anthropic) or bot tokens, remain in memory or environment files and are never written to static configuration storage.
However, a regression in the configuration I/O logic breaks this security model. When the application performs operations that require reading, modifying, and saving the configuration—specifically during automated updates, interactive configuration (openclaw configure), or self-healing routines (openclaw doctor --fix)—it fails to distinguish between the resolved runtime value and the original configuration source.
Consequently, the application overwrites the user's secure configuration file with the resolved in-memory state. A placeholder like ${OPENAI_API_KEY}, which is safe to check into version control, is replaced by the actual alphanumeric secret key sk-proj-..., which is strictly confidential. This transformation happens silently, often without the user's knowledge, until the file is inspected or inadvertently committed to a public repository.
The vulnerability resides in the configuration serialization pipeline located in src/config/config-io.ts. The root cause is a lack of separation between the canonical configuration (what is stored on disk) and the effective configuration (what is used in memory).
When OpenClaw initializes, it invokes a loader that parses the JSON file and immediately passes it through a resolution function, resolveConfigEnvVars. This function recursively walks the object tree and substitutes any string matching the pattern ${...} with the corresponding value from process.env. The resulting object is used by the application for all logic.
The critical flaw occurs in the writeConfigFile function. This function accepts the current configuration object state to save changes to disk. Because the application only maintains the resolved state in memory without keeping a reference to the original raw state or a map of interpolated fields, JSON.stringify serializes the actual secret values. The serialization logic assumes that the current value of a field is the desired persistent value, ignoring the fact that the value originated from an ephemeral environment source.
The following pseudo-code illustrates the logic flow responsible for the vulnerability. The application loads the config, interpolates it immediately, and then writes that interpolated version back to disk during updates.
src/config/config-io.ts)// LOAD: Reads JSON and immediately destroys the reference to "${VAR}"
function loadConfig() {
const raw = fs.readFileSync('openclaw.json', 'utf8');
const config = JSON.parse(raw);
// Vulnerability: Original formatting is lost here
return resolveEnvVars(config);
}
// SAVE: Writes the resolved values (secrets) to disk
function saveConfig(updatedConfig) {
// Vulnerability: Writes "sk-12345..." instead of "${API_KEY}"
const output = JSON.stringify(updatedConfig, null, 2);
fs.writeFileSync('openclaw.json', output);
}The fix, introduced in PR #4900, implements a mechanism to preserve the original interpolation syntax. It likely involves tracking which fields contained variables or performing a reverse-lookup against the original raw configuration before saving.
function saveConfig(updatedConfig, originalRawConfig) {
const outputConfig = clone(updatedConfig);
// FIX: Restore ${VAR} references for fields that haven't changed logically
for (const key of Object.keys(originalRawConfig)) {
if (isInterpolated(originalRawConfig[key])) {
// Revert the resolved value back to the placeholder
outputConfig[key] = originalRawConfig[key];
}
}
fs.writeFileSync('openclaw.json', JSON.stringify(outputConfig, null, 2));
}Exploitation of this vulnerability is trivial and often accidental, triggered by standard maintenance commands. An attacker with local access could trigger this to persist ephemeral secrets, or a user could trigger it unknowingly.
Reproduction Steps:
Setup: Create an openclaw.json file utilizing environment variable interpolation for a sensitive field.
{
"llm": {
"provider": "anthropic",
"apiKey": "${ANTHROPIC_API_KEY}"
}
}Environment: Export the corresponding secret in the current shell.
export ANTHROPIC_API_KEY="sk-ant-api03-sensitive-secret-value"Trigger: Execute a command that modifies configuration. The doctor command with the --fix flag is a reliable trigger as it attempts to normalize the configuration structure.
openclaw doctor --fixVerification: Inspect the file content. The placeholder is gone, replaced by the plaintext secret.
cat openclaw.json
# Output: "apiKey": "sk-ant-api03-sensitive-secret-value"The primary impact of this vulnerability is the Unintentional Exposure of Sensitive Information (CWE-200) and Cleartext Storage of Sensitive Information (CWE-312). While the vulnerability requires local execution to trigger, the downstream effects can be severe in DevOps and collaborative environments.
git commit -am "update config"), they may unknowingly push live production credentials to a shared or public repository.Users must upgrade OpenClaw immediately to prevent further exposure. If you have run any maintenance commands on affected versions, your secrets may already be exposed on disk.
Immediate Steps:
v2026.2.7 or later. This version includes the fix from PR #4900 which correctly handles environment variable preservation.grep -r "sk-" openclaw.json or manually inspect your configuration file to verify no cleartext secrets are present.${VAR} syntax manually.Long-term Hardening:
Ensure that openclaw.json is added to your .gitignore file if it contains any specific local configuration, or strictly use separate environment files (e.g., .env) that are never tracked.
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenClaw OpenClaw | <= v2026.2.6-3 | v2026.2.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-312 |
| Vulnerability Type | Information Disclosure |
| Attack Vector | Local / File System |
| Impact | Confidentiality Loss |
| Affected Component | Config I/O (openclaw.json) |
| CVSS Score | 7.4 (High) |
The application stores sensitive information in cleartext within a resource that might be accessible to another control sphere.