T09 · Insecure Skill Coding Practices
- Location
scripts/config.py:45- Finding
Plaintext API Key Persistence Without Input Validation or Permission Hardening
- Content
View full analysis
Vulnerability Details
File Location:
scripts/config.py, lines 45-67
Vulnerability Type: Plaintext credential storage and environment-file injection
Risk Level: MediumVulnerable 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 FalseTechnical Analysis
The function persistently writes the supplied API key to a plaintext
.envfile in the process's current working directory. It does not create or enforce restrictive file permissions, use a protected credential store, or perform an atomic secure write. A newly created file inherits permissions from the process umask, while an existing file retains any previously permissive mode.The API key is interpolated directly into the environment-file content without rejecting carriage returns or newline characters. Consequently, an attacker who can control the value passed to
set_api_key()can insert additional environment-file records. For example, a value containingvalid-key\nADDITIONAL_SETTING=attacker-valuewould be persisted as multiple lines.The Skill documentation explicitly directs the agent to collect a key from the user and call
scripts.config.set_api_key(), making t ...[truncated 1648 chars]- Remediation
View remediation
Remediation Suggestions
- Prefer obtaining the API key exclusively from the process environment or a platform credential manager rather than persisting it in the project directory.
- If local persistence is required, store the credential in an operating-system keychain or dedicated secret-management service.
- Reject values containing carriage returns, line feeds, NUL bytes, or other control characters before writing:
python if any(character in api_key for character in ("\r", "\n", "\0")): return False - Create secret files with mode
0600and verify or correct permissions on existing files before use. - Write updates atomically through a securely created temporary file, set restrictive permissions, flush the content, and replace the destination.
- Store the file in a predictable per-user configuration directory rather than the current working directory.
- Ensure
.envis excluded from source control, build artifacts, diagnostic bundles, and backups that are not authorized to contain secrets. - Document that the credential is sent in the
XBY-APIKEYheader to the configured remote API and provide a supported mechanism for revocation and rotation.
