T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/ari.py:55
- Finding
- Bearer API key can be transmitted to an arbitrary or plaintext custom endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ari.py:55-71` and `scripts/ari.py:300-320` **Vulnerability Type**: Insufficient validation of credential-bearing network destinations **Risk Level**: Medium ### Vulnerable Code ```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 ``` ```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: ``` ### Technical Analysis The custom API endpoint mechanism uses two environment variables as an accidental-redirection safeguard, but it does not validate the URL schem ...[truncated 2442 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require TLS for all credential-bearing remote endpoints: ```python parsed = urllib.parse.urlparse(override) if parsed.scheme != "https": raise SystemExit("Custom API endpoints must use HTTPS") ``` 2. If plaintext HTTP is required for local development, allow it only for loopback addresses such as `127.0.0.1`, `::1`, or `localhost`, and require a separate development-only flag. 3. Validate that the URL has: - An allowed scheme. - A non-empty hostname. - No embedded username or password. - No unexpected fragments. - A permitted port where appropriate. 4. Do not reuse a production `ari_live_*` credential with custom deployments. Use separate credentials scoped to each deployment. 5. Display the resolved API origin before device authorization or authenticated requests when it differs from the official service. 6. Consider requiring interactive approval of the exact custom origin or maintaining an explicit trusted-host allowlist in a protected local configuration file. 7. Apply the same origin validation consistently to JSON, SSE, public authorization, release, and export requests. ]]>
