T09 · Insecure Skill Coding Practices
- Location
scripts/config_manager.py:37- Finding
Plaintext API credential storage and full credential disclosure
- Content
View full analysis
None: """Persist key and secret to 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] Configuration saved to: {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)) # Exit code: 0 when configured, 1 otherwise sys.exit(0 if configured else 1) ``` The original source contains Chinese comments and user-facing messages; they are translated above without changing the relevant program behavior. ### Technical Analysis The configuration manager stores the reusable Xiangyun API key and secret in an ordinary plaintext JSON file. The file is opened with the process's default permission behavior, so its final access mode depends on the user's current `umask`. The implementation does not explicitly restrict the file to its owner. The `load` command then prints both credentials in full to standard output. This is unnecessary for determining whether the Skill is configured and can expose credentials through terminal history, captured command output, Agent transcripts, CI logs, or parent processes that collect stdout. In addition, `scripts/config_manager.py:67-68` accepts credentials through `--key` and `--secret` command-line arguments. Depending on the operating system and execution environment, command-line arguments may ...[truncated 1455 chars]- Remediation
View remediation
