T09 · Insecure Skill Coding Practices
- Location
upload.py:25- Finding
Overbroad Loading of Secrets from an Ancestor Environment File
- Content
View full analysis
None: env_file = Path(__file__).parent.parent.parent / ".env" if not env_file.is_file(): return for line in env_file.read_text().splitlines(): line = line.strip() if line and not line.startswith("#") and "=" in line: key, _, value = line.partition("=") os.environ.setdefault(key.strip(), value.strip()) ``` ### Technical Analysis The script needs only `DRBINARY_API_KEY`, but `load_env()` reads an ancestor `.env` file and copies every parsed key/value pair into the process environment. This violates least privilege by exposing unrelated credentials and configuration values to the entire Python process. The ancestor path is selected implicitly using `Path(__file__).parent.parent.parent`, and this behavior is not documented in `SKILL.md`. Any imported module, tracing hook, exception reporter, subprocess added in a future revision, or other code executing in the same process could access the additional secrets through `os.environ`. The current reviewed implementation does not transmit these unrelated environment variables, execute subprocesses, or contain evidence of intentional credential exfiltration. Exploitation therefore requires another component capable of reading the process environment. Nevertheless, loading unnecessary secrets expands the impact of a compromised dependency or later code change. ### Attack Path 1. A user or deployment places `upload.py` under a directory hierarchy whose third-level ancestor contains a `.env` file. 2. That file contains `DRBINARY_API_KEY` together with unrelated secrets such as cloud credentials, database passwords, or service tokens. 3. The user invokes `upload.py`, causing `load_env()` to parse the ancestor `.env`. 4. Every pa ...[truncated 1102 chars]- Remediation
View remediation
None: env_file = Path(__file__).resolve().parent / ".env" if not env_file.is_file() or "DRBINARY_API_KEY" in os.environ: return for raw_line in env_file.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, _, value = line.partition("=") if key.strip() == "DRBINARY_API_KEY": os.environ["DRBINARY_API_KEY"] = value.strip() return ``` 3. Use a predictable, documented configuration location rather than traversing implicitly to a shared ancestor directory. 4. Validate that the configuration file is a regular file owned by the expected user and is not writable by untrusted users where the deployment model permits such checks. 5. Keep the API key in a dedicated secret store or narrowly scoped environment variable rather than a shared `.env` containing unrelated credentials. 6. Document the exact credential-loading behavior and the external upload destination so users can make an informed decision before processing sensitive binaries. ]]>
