T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/oc-guard.py:105
- Finding
- Nested Secrets Are Exposed in Receipts and Predictable Temporary Artifacts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/oc-guard.py:46, 105-111, 647-649, 735-742, 774` **Vulnerability Type**: Incomplete secret redaction and plaintext sensitive-data storage **Risk Level**: High ### Vulnerable Code ```python SECRET_RE = re.compile(r"(secret|token|apikey|api_key|password)", re.IGNORECASE) ``` ```python def mask_value(path: str, value): if SECRET_RE.search(path): s = str(value) if len(s) <= 8: return "****" return s[:4] + "****" + s[-4:] return value ``` ```python if op == "set": if "value" not in c: raise ValueError(f"missing value for set: {path}") set_path(modified, path, c["value"]) shown = mask_value(path, c["value"]) applied.append({"op": op, "path": path, "value": shown}) ``` ```python LAST_PROPOSAL_PATH.write_text( json.dumps(proposal, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", ) report = { "intent": proposal.get("intent"), "risk": risk, "changes": applied, "proposalFile": str(LAST_PROPOSAL_PATH), } LAST_PLAN_PATH.write_text( json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", ) ``` ```python dump_json(LAST_PROPOSAL_PATH, proposal) ``` ### Technical Analysis Secret masking is based exclusively on the mutation path. It does not recursively inspect dictionaries or lists stored as the mutation value. A proposal can therefore set a broad path such as `/channels/feishu` while embedding `appSecret`, `token`, or other credentials below that path. Because the parent path does not contain a secret-related keyword, `mask_value()` returns the entire object unchanged. Even when a path is recognized as sensitive, the implementation preserves the first and last four characters of the credential. This still discloses credential material and conflicts with the project's stated guarantee that secrets are never exposed in receipts. The complete proposal is also written without redaction ...[truncated 1326 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace path-only masking with recursive redaction of dictionaries and lists. 2. Evaluate each nested key against a comprehensive, normalized sensitive-key policy. 3. Replace secret values completely with a fixed marker such as `[REDACTED]`; do not preserve prefixes or suffixes. 4. Avoid persisting raw proposals that may contain credentials. 5. If persistence is operationally necessary, use a user-owned directory with mode `0700` and create files with mode `0600`. 6. Generate a separately sanitized proposal for receipts and diagnostics. 7. Add tests for nested secrets, mixed-case keys, broad parent-path mutations, lists containing credentials, and short secret values. ]]>
