T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/search.py:2198
- Finding
- Provider API credentials can be transmitted to arbitrary configured endpoints## Vulnerability Details **File Location**: `scripts/search.py:2198-2249`, `scripts/search.py:3328-3355`, `scripts/search.py:3694-3802` **Vulnerability Type**: Unvalidated credential-bearing provider endpoint **Risk Level**: Medium ### Vulnerable Code ```python def search_querit( query: str, api_key: str, max_results: int = 5, language: str = "en", country: str = "us", time_range: Optional[str] = None, include_domains: Optional[List[str]] = None, exclude_domains: Optional[List[str]] = None, base_url: str = "https://api.querit.ai", base_path: str = "/v1/search", timeout: int = 30, ) -> dict: endpoint = base_url.rstrip("/") + base_path # ... headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } data = make_request(endpoint, headers, body, timeout=timeout) ``` The endpoint is also configurable through a command-line argument: ```python querit_config = config.get("querit", {}) parser.add_argument( "--querit-base-url", default=querit_config.get("base_url", "https://api.querit.ai"), help="Querit API base URL" ) parser.add_argument( "--querit-base-path", default=querit_config.get("base_path", "/v1/search"), help="Querit API path" ) ``` Other credential-bearing provider endpoints are similarly read from configuration without validating their origins: ```python api_url=linkup_config.get("api_url", "https://api.linkup.so/v1/search") api_url=firecrawl_config.get("api_url", "https://api.firecrawl.dev/v2/search") api_url=perplexity_config.get( "api_url", "https://api.kilo.ai/api/gateway/chat/completions" ) api_url=serpbase_config.get("api_url", "https://api.serpbase.com/search") api_url=keenable_config.get("api_url", "https://api.keenable.ai/v1/search") ``` ### Technical Analysis Provider API keys are attached to HTT ...[truncated 2475 chars]
- Remediation
- ## Remediation Suggestions 1. Define each provider's canonical HTTPS origin in `scripts/provider_registry.py` and construct request URLs from that trusted registry. 2. Before attaching credentials, require: - An `https` scheme. - No URL user-information component. - An exact hostname match against the provider's approved host. - An approved port, normally 443. 3. Remove `--querit-base-url` from ordinary runtime arguments, or require an explicit high-friction development option before accepting a custom origin. 4. If compatible private gateways must be supported, maintain a separate operator-controlled allowlist and clearly warn that provider credentials will be sent to the custom host. 5. Ensure authorization headers and credential-bearing request bodies are never forwarded to an unapproved redirect destination. 6. Add tests proving that HTTP URLs, metadata addresses, private destinations, look-alike domains, and arbitrary public hosts are rejected for credential-bearing provider requests. 7. Update the permission declaration if custom provider endpoints are intentionally retained; otherwise enforce the currently declared host restrictions in code.
