T09 · Insecure Skill Coding Practices
- Location
scripts/crisp_api.py:37- Finding
Bearer Credential Disclosure to Arbitrary or Plaintext Network Destinations
- Content
View full analysis
str: return (getattr(args, "base", None) or os.environ.get("CRISP_API_BASE") or DEFAULT_BASE).rstrip("/") def user_agent(args: argparse.Namespace) -> str: return getattr(args, "user_agent", None) or os.environ.get("CRISP_USER_AGENT") or DEFAULT_UA def request_json( args: argparse.Namespace, method: str, endpoint: str, body: dict[str, Any] | None = None, token: str | None = None, ) -> Any: if endpoint.startswith("http://") or endpoint.startswith("https://"): url = endpoint else: url = api_base(args) + "/" + endpoint.lstrip("/") data = None headers = { "User-Agent": user_agent(args), "Accept": "application/json", } if token is None: token = token_from_env_or_file(args) headers["Authorization"] = f"bearer {token}" ``` The relevant command-line inputs are unrestricted: ```python common.add_argument("--base", default=None) ... get.add_argument("endpoint") ``` ### Technical Analysis The request helper accepts an absolute HTTP or HTTPS URL as its endpoint. It also accepts an arbitrary API base through `--base` or `CRISP_API_BASE`. Regardless of the resulting host or transport security, it attaches the user's Crisp bearer token to the `Authorization` header. The declared Skill functionality only requires authenticated communication with Crisp. Forwarding the credential to arbitrary domains, or transmitting it over plaintext HTTP, exceeds the minimum privileges required for grocery planning. There is no validation of: - The URL scheme. - The destination hostname. - The expected HTTPS port. - The `/v1` API path. - ...[truncated 1765 chars]- Remediation
View remediation
