T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/yuboto_client.py:42
- Finding
- API Credential Disclosure Through an Unrestricted Base URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/yuboto_client.py:42-46, 61-75`; `scripts/yuboto_cli.py:191-196, 495` **Vulnerability Type**: Unrestricted credential-bearing outbound request **Risk Level**: High ### Vulnerable Code ```python class YubotoClient: def __init__(self, config: YubotoConfig): self.config = config self.headers = { "Accept": "application/json", "Content-Type": "application/json", "Authorization": self._build_auth_header(config.api_key), } ``` ```python def _url(self, path: str) -> str: return self.config.base_url.rstrip("/") + path def _request( self, method: str, path: str, *, params: Optional[Dict[str, Any]] = None, json_body: Optional[Dict[str, Any]] = None, ) -> Any: url = self._url(path) if params: qs = urllib.parse.urlencode({k: v for k, v in params.items() if v is not None}) if qs: url = f"{url}?{qs}" data = None if json_body is not None: data = json.dumps(json_body, ensure_ascii=False).encode("utf-8") req = urllib.request.Request( url=url, data=data, headers=self.headers, method=method.upper(), ) ``` ```python def build_client(args): api_key = args.api_key or os.getenv("OCTAPUSH_API_KEY") if not api_key: print("ERROR: missing API key. Use --api-key or OCTAPUSH_API_KEY env var.", file=sys.stderr) sys.exit(2) cfg = YubotoConfig( api_key=api_key, base_url=args.base_url, timeout=args.timeout, ) return YubotoClient(cfg) ``` ```python ap.add_argument("--base-url", default="https://api.yuboto.com") ``` ### Technical Analysis The CLI accepts an unrestricted `--base-url` value and passes it directly into `YubotoConfig`. The client then constructs every request from that value while unconditionally attaching the API credential as an `Authorization` header. No validation requi ...[truncated 1841 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require the base URL to use HTTPS: - Parse it with `urllib.parse.urlsplit`. - Reject every scheme other than `https`. - Reject embedded credentials, fragments, and malformed hostnames. 2. Apply an exact hostname allowlist: - Permit `api.yuboto.com` by default. - Do not use suffix-only checks that could accept domains such as `api.yuboto.com.attacker.example`. 3. If custom endpoints are required for testing: - Require an explicit flag such as `--allow-unsafe-custom-base-url`. - Display a prominent warning before attaching credentials. - Prefer separate test credentials with restricted privileges. - Never permit production credentials over cleartext HTTP. 4. Implement redirect controls: - Reject redirects to a different origin. - Ensure the `Authorization` header is never forwarded across host or scheme boundaries. 5. Add automated tests verifying rejection of: - HTTP URLs. - Attacker-controlled domains. - Look-alike domains. - URLs containing user information. - Cross-origin redirects. ]]>
