T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/generate_audio.py:4
- Finding
- Unnecessary Exposure of Environment Secrets to a Network-Capable TTS Subprocess<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_audio.py`, lines 4–17 **Vulnerability Type**: Unrestricted environment inheritance by an external subprocess **Risk Level**: Medium ### Vulnerable Code ```python from dotenv import load_dotenv load_dotenv() def generate_edge_tts(text, output_file, voice="zh-CN-XiaoxiaoNeural"): """Uses Edge-TTS (free, high quality).""" print(f"Generating Edge-TTS for: {text[:20]}...") cmd = [ "edge-tts", "--text", text, "--write-media", output_file, "--voice", voice ] subprocess.run(cmd, check=True) ``` ### Technical Analysis The script calls `load_dotenv()` without selecting individual required variables. This loads all values discovered in the `.env` file into the Python process environment, including potentially unrelated API keys, access tokens, passwords, or service credentials. The subsequent `subprocess.run()` call does not provide an explicit `env` argument. Child processes inherit the parent environment by default, so every loaded secret becomes accessible to the externally resolved `edge-tts` executable. The script does not use any of the loaded environment variables itself, making this exposure unnecessary. The executable is resolved through the process `PATH`. If an attacker can place a malicious executable named `edge-tts` earlier in `PATH`, replace the installed executable, or compromise the dependency, that executable can read and disclose all inherited `.env` values. Because Edge TTS is network-capable by design, inherited sensitive values could also be transmitted externally by a compromised implementation. The list-based subprocess invocation prevents shell metacharacter injection through `text`, `output_file`, or `voice`; the issue is environment exposure and executable trust rather than shell command injection. ### Attack Path 1. The user or deployment environment stores sensitive credentials in a project or discoverable `.env ...[truncated 1370 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `load_dotenv()` and the `python-dotenv` import because this script does not use any loaded environment variable. 2. Pass a minimal, allowlisted environment to the subprocess rather than inheriting the complete parent environment. Include only values required for executable operation, such as a trusted `PATH` and locale settings. 3. Resolve `edge-tts` from a trusted installation location and invoke it through a validated absolute path. Verify that the resolved file is not located in a user-controlled or project-local directory. 4. Pin and verify the `edge-tts` dependency through an approved dependency-management process. 5. Keep sensitive credentials outside broadly loaded project `.env` files where possible, and grant each credential only the permissions required for its intended service. 6. If credentials become necessary for a future TTS provider, retrieve only the specifically required variables and avoid forwarding unrelated secrets to child processes. Example hardened approach: ```python import os import subprocess EDGE_TTS_PATH = "/usr/local/bin/edge-tts" safe_env = { "PATH": "/usr/local/bin:/usr/bin:/bin", "LANG": os.environ.get("LANG", "C.UTF-8"), } subprocess.run( [ EDGE_TTS_PATH, "--text", text, "--write-media", output_file, "--voice", voice, ], check=True, env=safe_env, ) ``` ]]>
