T09 · Insecure Skill Coding Practices
Error
- Location
- openclaw_skill.py:128
- Finding
- API credentials and personal identifiers may be transmitted over plaintext HTTP## Vulnerability Details **File Location**: `openclaw_skill.py:128-132` (also affects requests at lines 145-159, 177-185, and 203-227); insecure configuration is documented at `OPENCLAW_INSTALL_CHECKLIST.md:20-22` **Vulnerability Type**: Transmission of sensitive information over an unencrypted channel **Risk Level**: High ### Vulnerable Code ```python def get_products(identity: str, api_key: str, base_url: str, timeout: int = 10) -> dict: payload = {"username": identity, "phone": identity, "api_key": api_key} url = f"{base_url}/products" try: response = requests.post(url, json=payload, timeout=timeout) ``` The same credential-bearing request pattern is used for order status, order history, and order creation: ```python payload = { "username": identity, "phone": identity, "api_key": api_key, "order_id": int(order_id), } url = f"{base_url.rstrip('/')}/order/status" response = requests.post(url, json=payload, timeout=timeout) ``` The installation checklist permits a remote plaintext HTTP endpoint: ```env KFC_PLATFORM_PHONE=your_platform_phone KFC_PLATFORM_API_KEY=your_platform_api_key KFC_PLATFORM_BASE_URL=http://your-backend-host:8888/api/openclaw ``` ### Technical Analysis Sending an identity and API key to the ordering backend is necessary for the Skill's declared functionality. However, accepting and documenting non-loopback HTTP endpoints exceeds the minimum safe network privilege needed for that functionality. `resolve_base_url()` and the request functions do not enforce HTTPS for remote endpoints. When an operator configures an `http://` backend, `requests.post()` transmits the phone number or username and reusable API key without transport encryption. Request timeouts do not provide confidentiality or server authentication. Placing the API key in the JSON body also increases the chance that it will be captured by application request logging, revers ...[truncated 1468 chars]
- Remediation
- ## Remediation Suggestions 1. Reject non-HTTPS URLs unless the destination is explicitly verified as loopback: ```python import ipaddress from urllib.parse import urlparse def validate_base_url(base_url: str) -> str: parsed = urlparse(base_url) host = parsed.hostname or "" is_loopback = host == "localhost" try: is_loopback = is_loopback or ipaddress.ip_address(host).is_loopback except ValueError: pass if parsed.scheme != "https" and not is_loopback: raise ValueError("Remote backend URLs must use HTTPS") return base_url.rstrip("/") ``` 2. Apply validation centrally in `resolve_base_url()` so every endpoint inherits the policy. 3. Replace the remote HTTP example in `OPENCLAW_INSTALL_CHECKLIST.md` with an HTTPS URL. Clearly state that HTTP is allowed only for loopback development. 4. Prefer a scoped, short-lived authorization token in the `Authorization` header rather than placing reusable secrets in request bodies. 5. Configure the backend and reverse proxies to redact authorization data and request bodies from logs. 6. Use separate read-only and order-creation scopes so compromise of a listing credential cannot authorize purchases. 7. Ensure TLS certificate verification remains enabled and do not introduce a `verify=False` bypass.
