T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/teleskopiq.py:13
- Finding
- Bearer API key can be transmitted to an arbitrary configurable endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/teleskopiq.py:13-39`, with additional credential-bearing use at `scripts/teleskopiq.py:78-87` and configuration documentation at `SKILL.md:8-11` **Vulnerability Type**: Unrestricted credential destination / server-side request forgery-like credential disclosure **Risk Level**: High ### Complete Code Snippet ```python ENDPOINT = os.environ.get("TELESKOPIQ_ENDPOINT", "https://teleskopiq.com/api/graphql") API_KEY = os.environ.get("TELESKOPIQ_API_KEY", "") def gql(query, variables=None): if not API_KEY: print("Error: TELESKOPIQ_API_KEY not set", file=sys.stderr) sys.exit(1) body = {"query": query} if variables: body["variables"] = variables r = requests.post( ENDPOINT, json=body, headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}, timeout=30, ) r.raise_for_status() data = r.json() if "errors" in data: print(f"GraphQL errors: {json.dumps(data['errors'], indent=2)}", file=sys.stderr) sys.exit(1) return data["data"] ``` The same endpoint and credential are used for the streaming AI request: ```python with requests.post( ENDPOINT, headers={ "Content-Type": "application/json", "Accept": "text/event-stream", "Authorization": f"Bearer {API_KEY}", }, data=payload, stream=True, timeout=180, ) as resp: ``` The documented configuration explicitly permits overriding the destination: ```bash export TELESKOPIQ_API_KEY="tsk_..." export TELESKOPIQ_ENDPOINT="https://teleskopiq.com/api/graphql" # optional, this is the default ``` ### Technical Analysis The program reads `TELESKOPIQ_ENDPOINT` directly from the environment and uses it as the destination for authenticated HTTP requests. It does not validate: - The URL scheme. - Whether TLS is required. - The destination hostname. - Whether the destination belongs to Teleskopiq. ...[truncated 1686 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require HTTPS: ```python from urllib.parse import urlparse parsed = urlparse(ENDPOINT) if parsed.scheme != "https": raise ValueError("TELESKOPIQ_ENDPOINT must use HTTPS") ``` 2. Allowlist the official origin by default: ```python ALLOWED_HOSTS = {"teleskopiq.com"} if parsed.hostname not in ALLOWED_HOSTS: raise ValueError("Untrusted Teleskopiq endpoint") ``` 3. If self-hosted endpoints are a supported requirement, require an explicit opt-in setting and display a clear warning before forwarding credentials. 4. Use separate credentials for custom endpoints rather than forwarding credentials intended for the hosted service. 5. Reject URLs containing embedded user information and restrict ports where practical. 6. Disable or carefully validate redirects for authenticated requests. Ensure authorization headers are never forwarded to a different origin. 7. Document that script content, prompts, style data, and the bearer credential are transmitted to the selected service. 8. Apply least-privilege server-side scopes to API keys so a disclosed content-generation key cannot perform unrelated account administration. ]]>
