T09 · Insecure Skill Coding Practices
- Location
- scripts/config.py:38
- Finding
- API key persisted in a plaintext working-directory file<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config.py:38-62` **Vulnerability Type**: Plaintext credential storage and unsafe credential-file handling **Risk Level**: Medium ### Vulnerable Code ```python def save_api_key_to_env(api_key: str) -> bool: try: env_path = Path(".env") lines = [] if env_path.exists(): lines = env_path.read_text(encoding="utf-8").splitlines() found = False new_lines = [] for line in lines: if line.startswith("XBY_APIKEY="): new_lines.append(f"XBY_APIKEY={api_key}") found = True else: new_lines.append(line) if not found: new_lines.append(f"XBY_APIKEY={api_key}") env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8") os.environ["XBY_APIKEY"] = api_key return True except Exception as e: print(f"保存API key失败: {e}") return False ``` The mandatory workflow in `SKILL.md:13-18` and `SKILL.md:31` directs the agent to request the key and persist it by invoking `scripts.config.set_api_key()`. ### Technical Analysis The Skill stores the user-supplied API key unencrypted in `.env`, using a path relative to the process working directory. The implementation does not: - Apply restrictive file permissions such as `0600`. - Verify the owner or permissions of an existing file. - Reject symbolic links. - Use atomic, exclusive file creation. - Ensure that `.env` is excluded from version control, backups, or artifact packaging. - Offer session-only use as the default. The relative path also makes the storage destination dependent on the caller's working directory. This can place the credential in a shared repository or other unintended location. If an attacker can prepare `.env` as a symbolic link, writing the API key may disclose it into an attacker-readable target or overwrite an accessible file. This persistence is not nec ...[truncated 1346 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Prefer session-only storage and keep the key solely in memory or in a process environment variable supplied by the user. 2. If persistence is explicitly requested, use an operating-system credential manager rather than a plaintext file. 3. If file-based storage is unavoidable: - Store the file under a dedicated per-user configuration directory. - Create it atomically with permissions set to `0600`. - Verify file ownership and reject symbolic links. - Avoid following redirects through parent-directory links. - Do not print or log the key. 4. Add `.env` to `.gitignore` and packaging exclusions. 5. Clearly disclose the storage location, retention period, and deletion procedure before persisting the key. 6. Provide a supported method to revoke and delete the stored credential. ]]>
