T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/config.py:46
- Finding
- API Key Persisted in a Predictable Plaintext File Without Explicit Permission Controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config.py`, lines 46-63 **Vulnerability Type**: Plaintext sensitive-data storage with insufficient file-permission controls **Risk Level**: Medium ### Vulnerable Code ```python def save_api_key_to_env(api_key: str) -> bool: """Persist the API key to the .env file.""" 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"Failed to save API key: {e}") return False ``` ### Technical Analysis The supplied API key is written in plaintext to `.env` in the process's current working directory. The implementation does not create the file with an explicit restrictive mode, inspect or repair the permissions of an existing file, or ensure that the selected path is private to the current user. For a newly created file, effective permissions depend on the host process's umask. If `.env` already exists, `Path.write_text()` preserves its existing permissions, which may allow access by other local users or processes. The predictable working-directory location also increases the chance that the file is copied into backups, included in an archive, exposed through a development environment, or accidentally committed to source control. The same secret is also copied into the process environment. Child processes launched after this assignment may inherit the value, expanding the number of ...[truncated 1106 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Avoid persistent storage by default. Keep the API key in memory or obtain it from a preconfigured environment variable. 2. If persistence is required, use the operating system's credential manager or keyring rather than a plaintext file. 3. If a file must be used: - Store it in a dedicated per-user configuration directory. - Create it atomically with mode `0600`. - Reject symbolic links and unexpected file types. - Check and repair permissions on existing files before reading or writing them. - Avoid relying solely on the process umask. 4. Do not propagate the key into `os.environ` unless child-process inheritance is explicitly required. 5. Add `.env` to `.gitignore` and packaging exclusion rules. 6. Document where the credential is stored, which third-party endpoint receives it, and how the user can revoke or delete it. 7. Provide a credential-removal function and recommend immediate rotation after suspected exposure. ]]>
