T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/hot_scanner.py:22
- Finding
- Hot Scanner exposes the complete process environment to a network-capable third-party executable<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hot_scanner.py:22-30` and `scripts/hot_scanner.py:387-391` **Vulnerability Type**: Excessive credential propagation to a subprocess **Risk Level**: High ### Vulnerable Code ```python # Load .env file if exists ENV_FILE = Path(__file__).parent.parent / ".env" if ENV_FILE.exists(): with open(ENV_FILE) as f: for line in f: line = line.strip() if line and not line.startswith("#") and "=" in line: key, value = line.split("=", 1) os.environ[key] = value ``` ```python env = os.environ.copy() result = subprocess.run( [bird_bin, "search", query, "-n", "15", "--json"], capture_output=True, text=True, timeout=30, env=env ) ``` ### Technical Analysis The scanner imports every assignment from the project `.env` file into the global process environment without restricting variable names. It then copies the entire environment and passes it to the third-party `bird` executable. Twitter/X access only requires a narrow set of authentication values, documented as `AUTH_TOKEN` and `CT0`. Passing every environment variable exceeds least privilege. The child process may receive unrelated cloud credentials, API keys, CI/CD secrets, database passwords, Agent configuration, or other tokens inherited from the parent process or loaded from `.env`. The audited Python code does not directly transmit these unrelated values, and its direct HTTP requests use hardcoded market-data destinations. Nevertheless, `bird` is network-capable and therefore becomes a potential exfiltration boundary for every inherited secret. ### Attack Path 1. A user or Agent runs the Skill in an environment containing unrelated sensitive variables. 2. Alternatively, unrelated secrets are stored in the project `.env` file. 3. `hot_scanner.py` imports every `.env` assignment into `os.environ`. 4. A social scan invokes `bird` and supplies a full copy of `os.environ`. 5. If the ...[truncated 767 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not modify the global `os.environ` when parsing `.env`. 2. Accept only explicitly required variables, such as `AUTH_TOKEN` and `CT0`. 3. Construct a minimal subprocess environment rather than copying the parent environment. 4. Preserve only essential runtime values such as a trusted `PATH`, locale, and required Twitter credentials. 5. Reject or ignore unknown `.env` keys. 6. Resolve and validate the expected `bird` executable before invocation. 7. Document that Twitter credentials are passed to an external executable. Example hardening pattern: ```python allowed = {"AUTH_TOKEN", "CT0"} credentials = {} if ENV_FILE.exists(): for raw_line in ENV_FILE.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if line and not line.startswith("#") and "=" in line: key, value = line.split("=", 1) key = key.strip() if key in allowed: credentials[key] = value.strip() child_env = { "PATH": "/usr/local/bin:/usr/bin:/bin", **credentials, } result = subprocess.run( [verified_bird_path, "search", query, "-n", "15", "--json"], capture_output=True, text=True, timeout=30, env=child_env, check=False, ) ``` ]]>
