T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/redact_openclaw_config.py:37
- Finding
- Sensitive-key values shorter than 24 characters bypass redaction<![CDATA[ ## Vulnerability Details **File Location**: `scripts/redact_openclaw_config.py`, lines 37–73 **Vulnerability Type**: Incomplete credential redaction **Risk Level**: High ### Vulnerable Code ```python def mask(s: str) -> str: s = s or "" if len(s) <= 8: return "***" return f"{s[:4]}…{s[-4:]}" def looks_secret(s: str) -> bool: if len(s) < 24: return False if s.startswith(("http://", "https://", "/", "./", "../", "~/")): return False return bool(JWT_LIKE_RE.match(s) or HEXISH_RE.match(s) or ALNUMISH_RE.match(s)) def redact_string(s: str) -> str: if looks_secret(s): return mask(s) return URL_QS_SECRET_RE.sub(lambda m: m.group("prefix") + mask(m.group("val")), s) def redact_obj(obj: Any) -> Any: if isinstance(obj, dict): out: dict[str, Any] = {} for key, value in obj.items(): skey = str(key) if SENSITIVE_KEY_RE.search(skey): if isinstance(value, str): out[skey] = redact_string(value) else: out[skey] = "***" else: out[skey] = redact_obj(value) return out ``` ### Technical Analysis When a key matches `SENSITIVE_KEY_RE`, its string value is passed to `redact_string()` rather than being unconditionally replaced. `redact_string()` only masks a standalone value if `looks_secret()` recognizes it as secret-like. The first condition in `looks_secret()` rejects every value shorter than 24 characters. Consequently, short passwords, API keys, session keys, cookies, and tokens remain unchanged unless they happen to appear as a recognized URL query parameter. This violates the script's documented security purpose: users are instructed to run it before sharing a configuration file and may reasonably treat its output as safe. The issue affects structured JSON and JSON5 processing. Retaining four-character prefixes and suffixes for longer credentials ...[truncated 1443 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Unconditionally replace every value associated with a sensitive key: ```python if SENSITIVE_KEY_RE.search(skey): out[skey] = "***" ``` 2. Do not preserve prefixes or suffixes of credentials. Partial credential disclosure provides little diagnostic value and may facilitate identification or brute-force attacks. 3. Apply the same unconditional policy in the raw-text fallback. A key classified as sensitive must have its value removed regardless of length, alphabet, or quoting style. 4. Expand handling to cover short bare values, numeric credentials, arrays, multiline strings, and unusual JSON5 syntax. 5. Add automated tests for: - Short passwords and tokens. - Nested sensitive keys. - Sensitive values in lists. - Numeric and Boolean values under sensitive keys. - JSON and JSON5 input. - URL query credentials. - Raw-text fallback behavior. 6. Emit a prominent warning when parsing fails and fallback redaction is used. 7. Continue instructing users to review output manually, but do not treat manual review as a substitute for deterministic redaction. ]]>
