T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/chainup_api.py:479
- Finding
- Arbitrary API Endpoint Can Receive Automatically Loaded Exchange Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/chainup_api.py:215-238` and `scripts/chainup_api.py:479-503` **Vulnerability Type**: Arbitrary credential destination and missing transport validation **Risk Level**: High ### Vulnerable Code ```python def request( self, method: str, path: str, *, signed: bool, query: Optional[Dict[str, Any]] = None, body: Optional[Dict[str, Any]] = None, ) -> Dict[str, Any]: method_u = method.upper() query = query or {} query = {k: v for k, v in query.items() if v is not None} body = {k: v for k, v in (body or {}).items() if v is not None} query_str = urlencode(query, doseq=True) request_path = path + (f"?{query_str}" if query_str else "") url = urljoin(self.cfg.base_url.rstrip("/") + "/", request_path.lstrip("/")) payload_bytes = None body_str_for_sign = None if method_u != "GET": body_str_for_sign = self._json_dumps_compact(body) if body else "{}" payload_bytes = body_str_for_sign.encode("utf-8") headers = { "Content-Type": "application/json", "admin-language": "en_US", "User-Agent": USER_AGENT, } if signed: ts_ms = str(int(time.time() * 1000)) headers["X-CH-APIKEY"] = self.cfg.api_key headers["X-CH-TS"] = ts_ms headers["X-CH-SIGN"] = self._sign( ts_ms, method_u, request_path, body_str_for_sign ) req = Request(url=url, data=payload_bytes, method=method_u, headers=headers) try: with urlopen(req, timeout=self.cfg.timeout) as resp: ``` ```python def _build_config(args: argparse.Namespace) -> ChainUpConfig: tools_cfg = _load_tools_config() base_url = ( args.base_url or tools_cfg.get("BASE_URL", "") or os.getenv("CHAINUP_BASE_URL", "") ) api_key = ( args.api_key or tools_cfg.get("API_KEY", "") or os.getenv("CHAINUP_API_KEY", "") ) secret_key = ( ...[truncated 3411 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Require HTTPS** - Parse the URL with `urllib.parse.urlparse`. - Reject any scheme other than `https`. - Reject URLs containing user information, fragments, or unexpected path components. 2. **Restrict credential destinations** - Maintain an explicit allowlist of approved exchange hostnames. - Compare normalized hostnames exactly; do not use suffix or substring matching. - Consider certificate or public-key pinning for tightly controlled deployments. 3. **Bind credentials to an origin** - Store each API key and secret together with its approved base URL. - Refuse to use credentials when the selected scheme, hostname, or port differs from the bound origin. 4. **Prevent unsafe source mixing** - If `--base-url` is provided, do not silently combine it with credentials from `/root/TOOLS.md` or environment variables. - Require an explicit, security-focused approval before sending inherited credentials to a newly selected origin. - Prefer named configuration profiles containing the URL and credentials as one atomic configuration unit. 5. **Validate before signing** - Perform all destination checks before constructing authentication headers or signatures. - Fail closed if URL parsing or hostname validation is ambiguous. 6. **Apply least-privilege exchange permissions** - Use read-only API keys for query-only workflows. - Separate trading and transfer credentials. - Disable withdrawal or transfer permissions unless strictly required. - Use exchange-side IP allowlisting where available. 7. **Add regression tests** - Verify that HTTP URLs are rejected. - Verify that unapproved hosts are rejected. - Verify that a CLI URL override cannot inherit credentials belonging to another origin. - Verify handling of hostname confusion, alternate ports, user-information components, redirects, and malformed URLs. ]]>
