T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/config.py:45
- Finding
- API Key Persisted in a Plaintext File Without Access Hardening<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config.py:45-66` **Vulnerability Type**: Plaintext storage of sensitive credentials **Risk Level**: Medium ### Vulnerable Code ```python def save_api_key_to_env(api_key: str) -> bool: """将API key保存到.env文件""" 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 ``` ### Technical Analysis The `save_api_key_to_env` function writes the user-supplied API key directly into a plaintext `.env` file in the process's current working directory. The implementation does not: - Enforce restrictive file permissions such as `0600`. - Verify whether an existing `.env` path is a regular file rather than a symbolic link. - Use a dedicated, user-private configuration directory. - Prevent the file from being included in source-control commits, backups, build artifacts, or diagnostic bundles. - Offer session-only credential handling or integration with an operating-system credential store. The actual exposure depends on the process umask, working directory permissions, repository practices, and other local processes. Nevertheless, the code itself provides no confidentiality controls beyond ordinary filesystem defaults. The Skill instructions at `SKILL.md:17-19` and `SKILL.md:33` explicitly direct the agent to collect the key and call `set_api_key`, making ...[truncated 1327 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Prefer session-only credential handling or an operating-system credential manager rather than writing the key to the project directory. 2. If file persistence is required, store the credential in a deterministic user-private configuration directory outside the repository. 3. Create the credential file atomically with permissions set to `0600`; verify and correct permissions on existing files before reading them. 4. Reject symbolic links and verify that the destination is a regular file owned by the expected user. 5. Add `.env` to `.gitignore` and relevant artifact, backup, and diagnostic exclusion lists. 6. Avoid retaining the credential in global process state longer than necessary. 7. Document where the key is stored, how it is protected, and how the user can revoke or delete it. 8. Add automated tests that verify restrictive permissions and safe handling of existing files and symbolic links. ]]>
