T09 · Insecure Skill Coding Practices
Error
- Location
- references/authentication.md:275
- Finding
- Bearer Credential Disclosure Through an Unrestricted Request URL## Vulnerability Details **File Location**: `references/authentication.md`, lines 275-307 **Vulnerability Type**: Credential disclosure and server-side request forgery caused by an unrestricted authenticated request destination **Risk Level**: High ### Vulnerable Code ```javascript async function makeAuthenticatedRequest(url, options = {}) { let response = await fetch(url, { ...options, headers: { ...options.headers, 'Authorization': `Bearer ${apiKey}` } }); if (response.status === 401) { // Refresh the API key const refreshResponse = await fetch('https://api.cal.com/v2/api-keys/refresh', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({}) }); if (refreshResponse.ok) { const { data } = await refreshResponse.json(); apiKey = data.apiKey; // Retry original request with new key response = await fetch(url, { ...options, headers: { ...options.headers, 'Authorization': `Bearer ${apiKey}` } }); } } return response; } ``` ### Technical Analysis The helper accepts an unrestricted `url` argument and unconditionally attaches the Cal.com bearer credential. It does not require a relative API path, validate the destination origin, restrict the scheme to HTTPS, or prevent redirects to an untrusted origin. If an attacker can influence `url`, the initial request discloses the current API key to the selected destination. The behavior following an HTTP 401 response makes the issue more severe: the helper requests a replacement API key and then transmits that newly generated key to the same unrestricted destination. The unrestricted request target can also create a server-side request forgery condition. Depending on the runtime's netw ...[truncated 1935 chars]
- Remediation
- ## Remediation Suggestions - Replace the arbitrary URL parameter with a relative Cal.com API path. - Resolve paths against a fixed base URL such as `https://api.cal.com/v2/`. - Before attaching credentials, enforce: - The `https:` scheme. - The exact expected hostname. - An approved port. - No URL user information. - An approved API path prefix. - Disable automatic cross-origin redirects or validate the destination after every redirect. - Never retry an authenticated request against a destination that has not passed origin validation. - Keep API-key refresh logic separate from general request logic. - Use narrowly scoped credentials and avoid platform-admin keys unless explicitly required. - Add tests covering attacker-controlled hosts, alternate ports, HTTP URLs, user-information URL syntax, redirect chains, loopback addresses, and private network addresses. A safer interface would resemble: ```javascript const CAL_API_ORIGIN = 'https://api.cal.com'; function buildCalApiUrl(path) { const url = new URL(path, 'https://api.cal.com/v2/'); if (url.origin !== CAL_API_ORIGIN || !url.pathname.startsWith('/v2/')) { throw new Error('Unapproved Cal.com API destination'); } return url; } ```
