Severity Assessment
CVSS Assessment
| Metric |
v3.1 |
v4.0 |
| Score |
7.7 / 10.0 |
8.3 / 10.0 |
| Severity |
High |
High |
| Vector |
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N |
| Calculator |
CVSS v3.1 Calculator |
CVSS v4.0 Calculator |
Threat Model Alignment
Classification: security-specific
This is security-specific because /config show is documented as an operator inspection surface, not a plaintext secret export primitive, while surrounding config and logging guidance treats secrets as data that should be redacted on shared or operator-visible surfaces. OpenClaw also supports channel reply modes where owner-triggered chat responses remain visible in shared channels or groups, so owner-only invocation does not erase the confidentiality boundary. Returning raw config secrets in the chat reply therefore violates the documented secrecy model rather than exercising an intentionally trusted admin capability.
Impact
The /config show chat command returns the full parsed config object as a JSON-formatted chat message with no secret redaction applied, exposing plaintext passwords, API keys, and bot tokens stored in the config file to the channel message history.
Affected Component
File: src/auto-reply/reply/commands-config.ts:101-135
const snapshot = await readConfigFileSnapshot();
// ...
const parsedBase = structuredClone(snapshot.parsed as Record<string, unknown>);
if (configCommand.action === "show") {
const pathRaw = configCommand.path?.trim();
if (pathRaw) {
// ...
const value = getConfigValueAtPath(parsedBase, parsedPath.path);
const rendered = JSON.stringify(value ?? null, null, 2);
return {
shouldContinue: false,
reply: {
text: `⚙️ Config ${pathRaw}:\n\`\`\`json\n${rendered}\n\`\`\``,
},
};
}
const json = JSON.stringify(parsedBase, null, 2);
return {
shouldContinue: false,
reply: { text: `⚙️ Config (raw):\n\`\`\`json\n${json}\n\`\`\`` },
};
}
Technical Reproduction
- Deploy OpenClaw with a config file containing at least one sensitive field (e.g.
gateway.token, irc.password, telegram.token, or any provider apiKey).
- As the configured owner, send
/config show on any enabled channel.
- Observe: the bot replies with a full JSON dump of
parsedBase — the raw parsed config — including any plaintext secret values. No values are masked or replaced with [REDACTED].
Alternatively, send /config show gateway.token to extract a specific secret field by path.
Demonstrated Impact
handleConfigCommand in commands-config.ts calls readConfigFileSnapshot() which returns the raw parsed config object at snapshot.parsed. It then calls structuredClone(snapshot.parsed) and immediately serializes this clone with JSON.stringify before returning it as the reply text. There is no call to redactConfigSnapshot() or redactConfigObject() anywhere in this path.
By contrast, the gateway's config.get HTTP endpoint (src/gateway/server-methods/config.ts:290) correctly calls redactConfigSnapshot(snapshot, schema.uiHints) before responding, which walks the schema and replaces all SecretInput / sensitive fields with the [REDACTED] sentinel.
Sensitive fields that can be exposed include: IRC password and nickserv password; gateway auth token and password; Slack signingSecret; Telegram token; Discord token; and all AI provider apiKey/token fields. These are marked as SecretInput or sensitive in the config schema (src/config/zod-schema.ts) but the chat command path never consults the schema hints.
Because the reply is delivered as a chat message, it is persisted in channel message history (Slack, Discord, iMessage, Telegram, etc.) and may be visible to any user with access to that channel history — including other channel members who are not the OpenClaw owner. The /config show <path> sub-command variant (lines 122–129) is equally affected, allowing targeted extraction of individual secrets by dot-path.
Existing controls do not prevent exploitation: the rejectNonOwnerCommand guard only checks that the sender is the configured owner, which is sufficient for issuing the command itself but does not constrain what data is returned in the reply. Log-level redaction in src/logging/redact.ts applies only to log output, not to chat reply text.
Environment
Affects all OpenClaw deployments where the config file contains at least one sensitive field and at least one messaging channel is enabled. Triggered by sending /config show from any owner session. No special runtime configuration required.
Remediation Advice
Apply redactConfigSnapshot() (from src/config/redact-snapshot.ts) to the parsed config clone before serializing it for the chat reply in handleConfigCommand, matching the pattern already used by the config.get gateway endpoint. Both the full-config path (line 131) and the per-path extraction path (line 122) must be covered.
Severity Assessment
CVSS Assessment
Threat Model Alignment
Classification:
security-specificThis is security-specific because
/config showis documented as an operator inspection surface, not a plaintext secret export primitive, while surrounding config and logging guidance treats secrets as data that should be redacted on shared or operator-visible surfaces. OpenClaw also supports channel reply modes where owner-triggered chat responses remain visible in shared channels or groups, so owner-only invocation does not erase the confidentiality boundary. Returning raw config secrets in the chat reply therefore violates the documented secrecy model rather than exercising an intentionally trusted admin capability.Impact
The
/config showchat command returns the full parsed config object as a JSON-formatted chat message with no secret redaction applied, exposing plaintext passwords, API keys, and bot tokens stored in the config file to the channel message history.Affected Component
File:
src/auto-reply/reply/commands-config.ts:101-135Technical Reproduction
gateway.token,irc.password,telegram.token, or any providerapiKey)./config showon any enabled channel.parsedBase— the raw parsed config — including any plaintext secret values. No values are masked or replaced with[REDACTED].Alternatively, send
/config show gateway.tokento extract a specific secret field by path.Demonstrated Impact
handleConfigCommandincommands-config.tscallsreadConfigFileSnapshot()which returns the raw parsed config object atsnapshot.parsed. It then callsstructuredClone(snapshot.parsed)and immediately serializes this clone withJSON.stringifybefore returning it as the reply text. There is no call toredactConfigSnapshot()orredactConfigObject()anywhere in this path.By contrast, the gateway's
config.getHTTP endpoint (src/gateway/server-methods/config.ts:290) correctly callsredactConfigSnapshot(snapshot, schema.uiHints)before responding, which walks the schema and replaces allSecretInput/sensitivefields with the[REDACTED]sentinel.Sensitive fields that can be exposed include: IRC
passwordand nickserv password; gateway authtokenandpassword; SlacksigningSecret; Telegramtoken; Discordtoken; and all AI providerapiKey/tokenfields. These are marked asSecretInputorsensitivein the config schema (src/config/zod-schema.ts) but the chat command path never consults the schema hints.Because the reply is delivered as a chat message, it is persisted in channel message history (Slack, Discord, iMessage, Telegram, etc.) and may be visible to any user with access to that channel history — including other channel members who are not the OpenClaw owner. The
/config show <path>sub-command variant (lines 122–129) is equally affected, allowing targeted extraction of individual secrets by dot-path.Existing controls do not prevent exploitation: the
rejectNonOwnerCommandguard only checks that the sender is the configured owner, which is sufficient for issuing the command itself but does not constrain what data is returned in the reply. Log-level redaction insrc/logging/redact.tsapplies only to log output, not to chat reply text.Environment
Affects all OpenClaw deployments where the config file contains at least one sensitive field and at least one messaging channel is enabled. Triggered by sending
/config showfrom any owner session. No special runtime configuration required.Remediation Advice
Apply
redactConfigSnapshot()(fromsrc/config/redact-snapshot.ts) to the parsed config clone before serializing it for the chat reply inhandleConfigCommand, matching the pattern already used by theconfig.getgateway endpoint. Both the full-config path (line 131) and the per-path extraction path (line 122) must be covered.