T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/config.py:42
- Finding
- API Key Persisted in a Predictable Plaintext File<![CDATA[ ## Vulnerability Details **File Location**: `scripts/config.py:42-61` **Vulnerability Type**: Plaintext credential storage with insufficient file-permission controls **Risk Level**: Medium ### Technical Analysis The `save_api_key_to_env` function stores the supplied API key directly in a predictable `.env` file: ```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 ``` The key is written without encryption and without explicitly applying restrictive permissions such as mode `0600`. For a newly created file, its effective permissions depend on the process umask. For an existing file, potentially unsafe permissions are retained. The predictable filename also increases the risk of exposure through source-control commits, backups, artifact collection, or access by another local process or account. The write is not atomic, which can additionally leave incomplete configuration data after interruption, although credential disclosure is the primary security concern. ### Attack Path 1. A user provides an API key as required by the Skill workflow. 2. The Agent calls `set_api_key`, which invokes `save_api_key_to_env`. 3. The function writes the credential as `XBY_APIKEY=<secret>` to `.env`. 4. An unauthorized local us ...[truncated 894 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Prefer an operating-system credential store, managed secret service, or platform-provided secret injection mechanism instead of persistent plaintext storage. 2. If file persistence is unavoidable: - Create the file atomically with permissions set to `0600`. - Verify that the file is owned by the expected account. - Reject or repair group-readable and world-readable permissions. - Write through a securely created temporary file and atomically replace the destination. 3. Add `.env` to `.gitignore` and exclude it from build artifacts, diagnostic bundles, and backups where possible. 4. Obtain explicit user consent before persisting the key and provide an option to use an environment-only, nonpersistent credential. 5. Support credential deletion and rotation, and document the storage location. 6. Never include the key in logs, exception messages, telemetry, or returned API results. ]]>
