T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/tbotjson.py:319
- Finding
- Webhook secret is printed and transmitted to a caller-controlled destination<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tbotjson.py:99-164, 188-203, 319-341` **Vulnerability Type**: Sensitive credential exposure and unrestricted outbound transmission **Risk Level**: High ### Complete Code Snippet ```python def _discover_runtime_env() -> Dict[str, str]: """Load the first .env we can find from candidate runtime dirs.""" for d in _candidate_runtime_dirs(): env_path = d / ".env" if env_path.exists() and env_path.is_file(): return _parse_dotenv(env_path) return {} def _resolve_webhook_key(cli_key: str) -> str: if cli_key: return cli_key env_key = os.getenv("WEBHOOK_KEY", "").strip() if env_key: return env_key dotenv = _discover_runtime_env() for k in ("WEBHOOK_KEY", "TBOT_WEBHOOK_KEY", "TVWB_KEY", "TV_WEBHOOK_KEY"): v = (dotenv.get(k) or "").strip() if v: return v unique_key = _resolve_unique_key(dotenv) if unique_key: return _generate_webhook_key(unique_key) for k, v in dotenv.items(): if re.search(r"webhook", k, re.I) and re.search(r"key", k, re.I) and v.strip(): return v.strip() return "" def _resolve_unique_key(dotenv: Dict[str, str]) -> str: unique_key = os.getenv("TVWB_UNIQUE_KEY", "").strip() if unique_key: return unique_key unique_key = (dotenv.get("TVWB_UNIQUE_KEY") or "").strip() if unique_key: return unique_key for d in _candidate_runtime_dirs(): key_path = d / ".keyfile" if key_path.exists() and key_path.is_file(): try: return key_path.read_text().strip() except Exception: continue return "" def post_json(url: str, payload: Dict[str, Any]) -> Tuple[int, str]: data = json.dumps(payload).encode("utf-8") req = request.Request( url, data=data, headers={"Content-Type": "application/json"}, method="POST", ...[truncated 2965 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never print or persist the unredacted webhook key: - Replace `payload["key"]` with a fixed redaction marker before logging. - Do not write the key to `--out` unless the user explicitly requests an unsafe raw export. - Ensure exception messages and response logging cannot echo credentials. 2. Restrict outbound destinations: - Permit loopback destinations by default. - Require an explicit security override for remote hosts. - Maintain an allowlist of trusted schemes, hosts, and ports. - Reject user-information URL components and non-HTTP(S) schemes. - Require HTTPS for all non-loopback destinations. 3. Handle redirects securely: - Disable redirects for authenticated POST requests, or only follow redirects that preserve the exact approved origin. - Never forward a secret-bearing request across origins. 4. Reduce secret-file discovery: - Prefer an explicitly configured credential source. - Do not scan generic current and parent directories for `.env` or `.keyfile`. - Verify ownership and restrictive permissions before reading credential files. 5. Separate diagnostic output from payload output: - Print only a redacted summary containing the destination, ticker, direction, and quantity. - Keep the secret solely in memory for the minimum time necessary. ]]>
