T09 · Insecure Skill Coding Practices
- Location
clawhub_tracker.py:33- Finding
Unrestricted .env Variables Propagate to the ClawHub Subprocess
- Content
View full analysis
Vulnerability Details
File Location:
clawhub_tracker.py:33-43, 225-228
Vulnerability Type: Environment poisoning through unrestricted configuration loading
Risk Level: MediumVulnerable Code
python _env_path = os.path.join(DATA_DIR, ".env") if os.path.exists(_env_path): with open(_env_path) as _f: for _line in _f: _line = _line.strip() if "=" in _line and not _line.startswith("#"): _k, _, _v = _line.partition("=") os.environ.setdefault(_k.strip(), _v.strip()) APP_ID = os.environ.get("CLAWHUB_FEISHU_APP_ID", "") APP_SECRET = os.environ.get("CLAWHUB_FEISHU_APP_SECRET", "") USER_OPEN_ID = os.environ.get("CLAWHUB_FEISHU_USER_OPEN_ID", "")The resulting process environment is implicitly inherited here:
python r = subprocess.run( [CLAWHUB_BIN, "inspect", slug, "--json"], capture_output=True, text=True, timeout=15, )Technical Analysis
The
.envparser accepts every variable name and inserts it into the global process environment, even though the application only requires three Feishu settings. No allowlist, key validation, or subprocess environment sanitization is applied.When
subprocess.runis called without an explicitenvargument, theclawhubchild process inherits the modified environment. Consequently, an attacker who can write the tracker’s.envfile may define runtime-control or tool-specific variables rather than merely changing Feishu settings. Depending on how the installedclawhubexecutable is implemented, variables such asNODE_OPTIONS,PYTHONPATH, or ClawHub-specific configuration variables could modify module loading, runtime behavior, network destinations, or credential handling.This does not independently grant write access to
.env; exploitation requires an attacker or compromised process that can already modify the tracker data directory. However, it converts data-directory write access into a potential exec ...[truncated 1458 chars]- Remediation
View remediation
Remediation Suggestions
- Do not copy arbitrary
.enventries intoos.environ. - Allowlist only the three supported keys:
CLAWHUB_FEISHU_APP_IDCLAWHUB_FEISHU_APP_SECRETCLAWHUB_FEISHU_USER_OPEN_ID
- Store parsed values in a private configuration dictionary rather than modifying the process-wide environment.
- Supply an explicit, sanitized environment to
subprocess.run. Preserve only variables necessary to locate and operate the trusted executable. - Validate
.envownership and permissions before reading it, and document mode0600for the file and0700for its directory. - Resolve and validate the
clawhubexecutable path before execution.
Example hardening approach:
python ALLOWED_ENV_KEYS = { "CLAWHUB_FEISHU_APP_ID", "CLAWHUB_FEISHU_APP_SECRET", "CLAWHUB_FEISHU_USER_OPEN_ID", } config = {} if os.path.exists(_env_path): with open(_env_path, encoding="utf-8") as env_file: for line in env_file: line = line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) key = key.strip() if key in ALLOWED_ENV_KEYS: config[key] = value.strip() APP_ID = os.environ.get( "CLAWHUB_FEISHU_APP_ID", config.get("CLAWHUB_FEISHU_APP_ID", ""), )Use a sanitized child environment:
python child_env = { "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin", "HOME": os.path.expanduser("~"), } r = subprocess.run( [CLAWHUB_BIN, "inspect", slug, "--json"], capture_output=True, text=True, timeout=15, env=child_env, )- Do not copy arbitrary
