T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/dlazy_client.py:61
- Finding
- Bearer credential can be transmitted to an arbitrary user-configured endpoint<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/dlazy_client.py:61-79` - `scripts/dlazy_client.py:94-104` - `scripts/dlazy_ppt_runtime.py:194-206` - `docs/image-model-configuration.md:23-24, 42-47` **Vulnerability Type**: Unvalidated credential destination and insecure transport configuration **Risk Level**: High ### Vulnerable Code ```python def base_url() -> str: return (os.getenv("DLAZY_BASE_URL") or DEFAULT_BASE_URL).strip().rstrip("/") def api_key() -> Optional[str]: return (os.getenv("DLAZY_API_KEY") or "").strip() or None def _headers() -> Dict[str, str]: key = api_key() if not key: raise DlazyError( f"DLAZY_API_KEY is not set. Get a key from {API_KEY_URL} and save it with " "`python3 scripts/dlazy_ppt_runtime.py config --api-key <key>`." ) return { "Authorization": f"Bearer {key}", "Content-Type": "application/json", "X-CLI-Version": CLI_VERSION, } ``` ```python def upload_file(path: Path) -> str: """Upload a local image to dLazy storage and return its public URL.""" requests = _requests() filename = path.name content_type = mimetypes.guess_type(filename)[0] or "application/octet-stream" resp = requests.post( f"{base_url()}/api/cli/upload-url", headers=_headers(), json={"filename": filename, "contentType": content_type}, timeout=60, ) ``` ```python def _manifest_request(base_url: str, api_key: str, timeout: int) -> Optional[dict]: """Fetch the tool manifest - the cheapest call that proves the key works.""" endpoint = base_url.rstrip("/") + "/api/cli/tool/manifest" req = urllib.request.Request( endpoint, headers={ "Authorization": f"Bearer {api_key}", "X-CLI-Version": CLI_VERSION, }, method="GET", ) try: with urllib.request.urlopen(req, timeout=timeout) as resp: print(f"tool manifest: HTTP {res ...[truncated 2887 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the base URL with `urllib.parse.urlsplit` before any request. 2. Permit only `https` by default. Reject plaintext HTTP except for an explicit development-only localhost option. 3. Reject URLs containing embedded user information, fragments, or unsupported schemes. 4. Use `https://dlazy.com` as the only destination for dLazy-issued credentials by default. 5. Require a distinct credential option for self-hosted deployments rather than automatically forwarding `DLAZY_API_KEY`. 6. If custom remote hosts must be supported, display the normalized hostname and require explicit user confirmation before saving or transmitting a credential. 7. Consider an administrator-managed allowlist for approved self-hosted domains. 8. Validate that upload URLs use HTTPS and, where feasible, belong to an approved storage-domain allowlist. 9. Document that changing the base URL changes the party receiving the API key, prompts, and uploaded images. 10. Add tests confirming rejection of: - `http://example.com` - URLs with embedded credentials - unsupported schemes such as `file:` or `ftp:` - unapproved external domains when allowlisting is enabled ]]>
