T09 · Insecure Skill Coding Practices
- Location
scripts/config_manager.py:35- Finding
Plaintext API Credential Storage and Disclosure
- Content
View full analysis
None: """将 key 和 secret 持久化写入 config.json。""" data = load_config() data["key"] = key.strip() data["secret"] = secret.strip() with open(CONFIG_PATH, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"[OK] 配置已保存至: {CONFIG_PATH}") ``` ```python if args.command == "load": cfg = load_config() configured = is_configured(cfg) output = { "configured": configured, "key": cfg.get("key", ""), "secret": cfg.get("secret", ""), "config_path": CONFIG_PATH, } print(json.dumps(output, ensure_ascii=False, indent=2)) ``` ### Technical Analysis The credential manager writes the OCR API key and secret directly to `config.json` without encryption or explicit restrictive file permissions. The effective permissions therefore depend on the process umask and may allow other local users or processes to read the file. Credentials are also accepted through command-line arguments, as documented by the Skill, which can expose them through shell history, process inspection, command logging, or orchestration telemetry. The `load` command then prints both credentials verbatim to standard output. This unnecessarily increases the number of disclosure channels and exceeds the minimum access needed to verify whether the Skill is configured. No live credentials were embedded in the reviewed package; the shipped `config.json` contains empty values. ### Attack Path 1. A user runs the documented `save --key ... --secret ...` command. 2. The shell records the credentials in command history, or another local process observes the command-line arguments. 3. The manager writes the credentials to `config.json` using ...[truncated 625 chars]- Remediation
View remediation
