T09 · Insecure Skill Coding Practices
- Location
scripts/civitai.py:14- Finding
Overbroad ingestion of secrets from workspace environment files
- Content
View full analysis
None: candidates = [start / ".env", start.parent / ".env"] for env_path in candidates: if not env_path.exists(): continue for raw_line in env_path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) os.environ.setdefault(key.strip(), value.strip()) return ``` ### Technical Analysis The declared functionality requires only the `CIVITAI_API_KEY` value. However, `load_env_file()` reads every assignment from the first matching `.env` file and copies all parsed values into the process environment. The search covers both the script directory and its parent directory. Consequently, a shared workspace `.env` file may cause unrelated database credentials, cloud keys, access tokens, or other secrets to be loaded even though the Skill does not need them. This violates least-privilege principles by granting the running process access to a broader secret set than required. The current reviewed implementation uses only `CIVITAI_API_KEY`, relies exclusively on Python standard-library imports, and does not spawn child processes or transmit unrelated environment variables. Therefore, no present end-to-end exfiltration path for those additional secrets was identified. Nevertheless, placing them in process-global state unnecessarily increases exposure to diagnostics, future code changes, subsequently imported code, or child processes added later. ### Attack Path 1. A user or automation stores several credentials in a shared `.env` file located in the script directory or its parent. 2. The user invokes `scripts/civit ...[truncated 1378 chars]- Remediation
View remediation
str | None: for env_path in (start / ".env", start.parent / ".env"): if not env_path.is_file(): continue for raw_line in env_path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) if key.strip() == "CIVITAI_API_KEY": return value.strip() return None return None ``` 2. Keep the token in a local variable rather than copying file contents into the process-global environment: ```python token = os.getenv("CIVITAI_API_KEY") or load_civitai_token(script_dir) ``` 3. Document the precise `.env` lookup locations and recommend restrictive file permissions. 4. Avoid passing tokens through `--token` where practical because command-line arguments can be retained in shell history or exposed through process inspection. 5. Continue restricting requests containing authorization headers to the fixed HTTPS Civitai origin. If redirects are supported, ensure authorization data cannot be forwarded to another host. 6. Warn users before printing token-bearing download URLs, and offer a safer mode that writes the URL to a permission-restricted file or performs the download without displaying the credential. ]]>
