T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/smartbill_cli.py:58
- Finding
- Arbitrary API Base URL Can Expose SmartBill Credentials and Invoice Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/smartbill_cli.py:58-59, 100-109, 122-154` **Vulnerability Type**: Unrestricted credential and sensitive-data destination **Risk Level**: High ### Vulnerable Code ```python base_url = args.base_url if args.base_url is not None else os.getenv("SMARTBILL_API_BASE", DEFAULT_BASE_URL) ``` ```python return cls( username=username, token=token, base_url=base_url.rstrip("/"), timeout_seconds=timeout, retries=retries, ) ``` ```python class SmartBillClient: def __init__(self, config: ClientConfig): self.config = config auth_value = f"{config.username}:{config.token}".encode("utf-8") self._auth_header = f"Basic {base64.b64encode(auth_value).decode('ascii')}" def _request( self, method: str, path: str, query: Optional[Dict[str, Any]] = None, json_body: Optional[Dict[str, Any]] = None, accept: str = "application/json", expect_binary: bool = False, ) -> Tuple[Any, Dict[str, str]]: url = f"{self.config.base_url}{path}" if query: compact_query = {k: v for k, v in query.items() if v is not None} if compact_query: url = f"{url}?{urlencode(compact_query)}" payload: Optional[bytes] = None if json_body is not None: payload = json.dumps(json_body).encode("utf-8") for attempt in range(self.config.retries + 1): headers = { "Authorization": self._auth_header, "Accept": accept, } if payload is not None: headers["Content-Type"] = "application/json" request = Request(url=url, data=payload, headers=headers, method=method) try: with urlopen(request, timeout=self.config.timeout_seconds) as response: ``` ### Technical Analysis The CLI accepts the API destination from either the `--base-url` argument ...[truncated 2839 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Allowlist the production origin** - Parse the URL with `urllib.parse.urlsplit`. - Require the normalized production origin to be exactly `https://ws.smartbill.ro`. - Require the expected `/SBORO/api` base path. 2. **Require encrypted transport** - Reject all non-HTTPS URLs. - Reject URLs containing user information, fragments, unexpected ports, or malformed hostnames. 3. **Make custom endpoints explicitly unsafe** - If custom endpoints are genuinely required for development, disable them in normal operation. - Require a separate explicit option such as `--allow-unsafe-custom-endpoint`. - Display the normalized destination and require confirmation before attaching credentials. - Use separate test credentials that cannot access production SmartBill data. 4. **Restrict redirects** - Disable redirects for authenticated API calls or permit only same-origin HTTPS redirects. - Never forward the Authorization header when the scheme, hostname, or port changes. 5. **Separate trust domains** - Do not automatically reuse production credentials for custom endpoints. - Require credentials to be explicitly associated with an approved endpoint. 6. **Add security tests** - Verify rejection of HTTP URLs, attacker-controlled hosts, embedded credentials, alternate ports, malformed URLs, and cross-origin redirects. ]]>
