T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/gemini_smart_search.sh:7
- Finding
- Executable and Overly Broad Loading of Repository-Local Environment Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gemini_smart_search.sh:7-12`; related behavior in `scripts/gemini_smart_search.py:66-84` **Vulnerability Type**: Unsafe configuration-file execution and unrestricted environment-variable import **Risk Level**: Medium ### Complete Vulnerable Code `scripts/gemini_smart_search.sh:7-12`: ```bash if [ -f "$SKILL_DIR/.env.local" ]; then set -a # shellcheck disable=SC1090 . "$SKILL_DIR/.env.local" set +a fi ``` Related Python configuration loading in `scripts/gemini_smart_search.py:66-84`: ```python def load_repo_local_env() -> None: if os.environ.get("GEMINI_SMART_SEARCH_SKIP_LOCAL_ENV") == "1": return script_dir = Path(__file__).resolve().parent env_path = script_dir.parent / ".env.local" if not env_path.exists(): return 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) key = key.strip() value = value.strip() if not key or key in os.environ: continue if value and len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}: value = value[1:-1] os.environ[key] = value ``` ### Technical Analysis The shell wrapper loads `.env.local` using the Bash `.` command. This does not parse the file as passive key-value configuration; it executes the entire file as shell code in the wrapper's process. A crafted file can contain command substitutions, shell commands, redirections, functions, or other Bash constructs. These execute before the wrapper invokes the Python search implementation. The Python loader avoids direct shell execution, but it accepts every key found in `.env.local` and inserts it into `os.environ`. The Skill only needs `SMART_SEARCH_GEMINI_API_KEY` and the compatibility fallback `GEMINI_API_KEY`. Importing ...[truncated 2369 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove shell sourcing entirely.** The wrapper should invoke the canonical Python implementation without evaluating `.env.local`: ```bash exec python3 "$SCRIPT_DIR/gemini_smart_search.py" "$@" ``` 2. **Use one non-executable configuration parser.** Keep `.env.local` handling exclusively in Python and treat it strictly as data. 3. **Allowlist required variables.** Only accept: - `SMART_SEARCH_GEMINI_API_KEY` - `GEMINI_API_KEY` Ignore or reject every other key. 4. **Avoid process-wide environment mutation.** Parse the required values into local variables and pass the resolved API key directly to the request function rather than inserting arbitrary entries into `os.environ`. 5. **Validate configuration syntax.** Reject malformed names, duplicate assignments, unexpected quoting, multiline values, and shell constructs. A strict variable-name expression such as `^[A-Z_][A-Z0-9_]*$` should be used in addition to the allowlist. 6. **Check secret-file security.** Where supported, reject `.env.local` when it is a symbolic link, is not owned by the expected user, or is writable by group or other users. Recommend permissions equivalent to `0600`. 7. **Update documentation.** State that `.env.local` is parsed as non-executable configuration and must contain only the supported API-key fields. 8. **Add regression tests.** Verify that shell syntax in `.env.local` is never executed and that unrelated variables such as proxy settings are not imported. ]]>
