T09 · Insecure Skill Coding Practices
Error
- Location
- quad_check.py:290
- Finding
- Sensitive Configuration Values Are Exposed Through Diff Output<![CDATA[ ## Vulnerability Details **File Location**: `quad_check.py:290-292`, with the output sink at `quad_check.py:441-443` **Vulnerability Type**: Plaintext exposure of sensitive configuration values **Risk Level**: High ### Vulnerable Code ```python else: diff["changed"].append({ "path": current_path, "old": str(old[key])[:100], "new": str(new[key])[:100] }) ``` The command-line interface subsequently serializes the complete results: ```python summary = qc.get_summary() print("\n=== Quad Check Summary ===") print(json.dumps(summary, indent=2, ensure_ascii=False)) ``` ### Technical Analysis The recursive diff implementation stores the raw previous and current values of every changed non-dictionary field. It applies only a 100-character length limit and does not redact values based on their key names or locations. OpenClaw configuration files can contain credentials such as channel tokens, API keys, passwords, authorization headers, and provider secrets. The project itself references fields such as `channels.discord.token`, `apiKeys`, and `credentials`. Changes to these fields therefore place the old and new secret values in the `CheckResult.details` structure. When `quad_check.py` is invoked directly, `get_summary()` includes these details and the CLI prints the resulting JSON to standard output. Applications importing this module can also inadvertently forward or persist the unredacted summary. This behavior contradicts the declared security boundary that the Skill does not directly access credentials or API keys. ### Attack Path 1. A user changes a token, API key, password, or other secret in an OpenClaw JSON configuration file. 2. A previous snapshot containing the old value exists. 3. The user or an automated process invokes: ```bash python3 quad_check.py ~/.openclaw/openclaw.json ``` 4. `_compute_diff()` records up to 100 characters of both the old and new values. 5. `get_summary()` includes the unr ...[truncated 698 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never include raw configuration values in diff results by default. Report only: - The configuration path. - Whether the field was added, removed, or changed. - The value type, if operationally necessary. 2. Recursively redact fields whose names contain terms such as: - `token` - `secret` - `password` - `credential` - `apiKey` - `authorization` - `privateKey` 3. Treat arrays and nested structures as sensitive because credentials may appear inside them. 4. If value-level diagnostics are required, make them an explicit opt-in debug mode and display a prominent warning. 5. Ensure debug output remains redacted unless the user explicitly requests local secure output. 6. Add automated tests confirming that current and historical secret values never appear in: - `CheckResult.details` - `get_summary()` - CLI output - Log files 7. Review existing logs and transcripts for previously exposed credentials and rotate any affected secrets. ]]>
