T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/ragflow_ping.py:33
- Finding
- Bearer token can be transmitted over plaintext HTTP or forwarded during redirects## Vulnerability Details **File Location**: `scripts/ragflow_ping.py:33-39, 47-58`; `scripts/ragflow_smoke.py:34-41, 48-56`; `scripts/ragflow_status.py:31-38, 45-48`; `examples/api-examples.sh:19, 34-48` **Vulnerability Type**: Unprotected transmission of credentials and insufficient destination validation **Risk Level**: High ### Vulnerable Code `scripts/ragflow_ping.py:33-39`: ```python def http_get(url: str, api_key: str | None = None, timeout: int = 10) -> tuple[int, bytes]: headers = {"Accept": "application/json"} if api_key: headers["Authorization"] = f"Bearer {api_key}" req = urllib.request.Request(url, headers=headers, method="GET") try: with urllib.request.urlopen(req, timeout=timeout) as resp: return resp.status, resp.read() ``` `scripts/ragflow_ping.py:47-58`: ```python base_url = get_env("RAGFLOW_BASE_URL").rstrip("/") api_key = os.environ.get("RAGFLOW_API_KEY", "").strip() or None st, _ = http_get(f"{base_url}/openapi.json", api_key=None) if st != 200: print(f"LIVENESS_FAIL openapi.json status={st}") return 2 if not api_key: print("OK_LIVE (no api key set)") return 0 st2, body2 = http_get(f"{base_url}/v1/system/status", api_key=api_key) ``` `scripts/ragflow_smoke.py:34-41`: ```python def http_get(url: str, api_key: str, timeout: int = 15) -> tuple[int, bytes]: headers = { "Accept": "application/json", "Authorization": f"Bearer {api_key}", } req = urllib.request.Request(url, headers=headers, method="GET") try: with urllib.request.urlopen(req, timeout=timeout) as resp: return resp.status, resp.read() ``` `scripts/ragflow_status.py:31-38`: ```python def http_get(url: str, api_key: str, timeout: int = 15) -> tuple[int, bytes]: headers = { "Accept": "application/json", "Authorization": f"Bearer {api_key}", } re ...[truncated 3183 chars]
- Remediation
- ## Remediation Suggestions 1. Parse `RAGFLOW_BASE_URL` before making requests and permit only `https` by default. 2. Allow plaintext HTTP only for explicit loopback destinations such as `127.0.0.1`, `::1`, or `localhost`, or behind a clearly named opt-in such as `RAGFLOW_ALLOW_INSECURE_HTTP=1`. 3. Reject URLs containing embedded user information, fragments, unexpected schemes, or malformed hostnames. 4. Disable redirects for authenticated requests, or implement a redirect handler that permits only same-scheme, same-host, and same-port redirects. 5. Never downgrade an authenticated request from HTTPS to HTTP. 6. Configure certificate verification with the system trust store or an explicitly supplied private CA. Do not introduce a global TLS-verification bypass. 7. Apply the same validation to all Python helpers, shell examples, and documented curl commands. 8. Use a narrowly scoped monitoring credential with short lifetime and straightforward revocation. 9. Add automated tests covering plaintext remote URLs, cross-origin redirects, HTTPS-to-HTTP redirects, URLs with user information, and loopback exceptions.
