T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/ari.py:55
- Finding
- Bearer API Key Can Be Transmitted to a Custom Plaintext HTTP Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ari.py:55-71` and `scripts/ari.py:300-320` **Vulnerability Type**: Sensitive credential transmission over an unencrypted connection **Risk Level**: Medium ### Vulnerable Code Custom API endpoints are accepted without validating that the URL uses HTTPS: ```python def base_url(): """API 基址。ARI_BASE_URL 覆盖必须同时显式设置 ARI_ALLOW_CUSTOM_BASE=1 才生效: 所有请求(含带 Bearer Key 的)都发往这里,若单凭一个环境变量就能改指向, 会话里被注入的一条 shell 命令就足以把 Key 重定向到第三方主机。双变量门槛 让「指向哪」与「我确认这是自己的环境」成为两个独立动作。 """ override = (os.environ.get("ARI_BASE_URL") or "").strip().rstrip("/") if not override or override == PROD_BASE: return PROD_BASE if (os.environ.get("ARI_ALLOW_CUSTOM_BASE") or "").strip() != "1": emit(error_obj( "ARI_CUSTOM_BASE_BLOCKED", 0, "ARI_BASE_URL 指向非官方地址:%s,已拒绝发送请求" % override, "若这是你自己的开发/自建环境,请同时设置 ARI_ALLOW_CUSTOM_BASE=1 后重试;" "若你并未主动设置过 ARI_BASE_URL,请勿继续,先清除该环境变量。")) raise SystemExit(2) return override ``` Authenticated requests then attach the reusable API key to the selected endpoint: ```python def request_json(method, path, payload=None, params=None): query = { "method": method, "path": path, "params": {k: v for k, v in (params or {}).items() if v not in (None, "")}, "payload": payload, } url = base_url() + path if query["params"]: url += "?" + urllib.parse.urlencode(query["params"], doseq=True) data = None if payload is None else json.dumps(payload).encode("utf-8") headers = { "Authorization": "Bearer " + require_key(), "Accept": "application/json", "User-Agent": user_agent(), } if data is not None: headers["Content-Type"] = "application/json" try: req = urllib.request.Request(url, data=data, headers=headers, method=method) with urllib.request.urlopen(req, timeout=TIMEOUT_SEC) as resp: ``` ### Tec ...[truncated 2569 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Require HTTPS for custom remote endpoints.** Parse the URL with `urllib.parse.urlparse` and reject any non-HTTPS scheme before returning it: ```python parsed = urllib.parse.urlparse(override) if parsed.scheme != "https" or not parsed.hostname: raise SystemExit("Custom ARI endpoints must use HTTPS") ``` 2. **Provide a narrowly scoped local-development exception.** If plaintext HTTP is necessary for development, allow it only for loopback destinations such as `127.0.0.1`, `::1`, or `localhost`, and require a separate explicit flag such as `ARI_ALLOW_INSECURE_LOCAL_HTTP=1`. 3. **Do not permit HTTP for arbitrary private-network hosts.** Private networks can still contain untrusted users, compromised routers, transparent proxies, and traffic-capture systems. 4. **Validate redirects.** Ensure authenticated requests cannot follow redirects from an approved HTTPS origin to HTTP or to an unapproved host while retaining the `Authorization` header. 5. **Use scoped and revocable credentials.** Where supported, issue custom or development endpoints separate API keys with minimum permissions, limited lifetime, and no billing authority. 6. **Document certificate configuration.** Support trusted private certificate authorities for self-hosted installations rather than recommending plaintext HTTP when standard public certificates are unavailable. 7. **Add regression tests** covering: - Rejection of arbitrary `http://` endpoints. - Acceptance of valid `https://` endpoints. - Optional loopback-only development behavior. - Rejection of malformed URLs and unsupported schemes. - Prevention of credential-bearing cross-origin or HTTPS-to-HTTP redirects. ]]>
