T09 · Insecure Skill Coding Practices
- Location
scripts/expense-tracker.js:248- Finding
Unrestricted Supabase Endpoint Can Expose API Credentials and Financial Records
- Content
View full analysis
{ config.supabase = { url: url.trim() }; rl.question('Anon Key: ', (key) => { config.supabase.api_key = key.trim(); if (saveConfig(config)) { log('Supabase configured', 'green'); } rl.close(); }); }); ``` ```javascript async function supabaseAdd(config, record) { const { url, api_key } = config.supabase; const response = await fetch(`${url}/rest/v1/expenses`, { method: 'POST', headers: { 'Authorization': `Bearer ${api_key}`, 'Content-Type': 'application/json', 'apikey': api_key }, body: JSON.stringify(record) }); return response.ok; } async function supabaseList(config) { const { url, api_key } = config.supabase; const response = await fetch(`${url}/rest/v1/expenses?order=date.desc`, { headers: { 'Authorization': `Bearer ${api_key}`, 'apikey': api_key } }); if (!response.ok) return []; return await response.json(); } ``` ### Technical Analysis The Supabase URL is accepted as arbitrary text and subsequently used as the destination for authenticated requests. The implementation does not parse the value with `URL`, require HTTPS, restrict the destination to an expected Supabase host, or reject loopback, private, link-local, and cloud metadata addresses. Both request functions attach the configured Supabase key as an `Authorization` bearer token and an `apikey` header. `supabaseAdd` additionally transmits the complete financial record, including its amount, category, note, date, and identifier. Remote synchronization is consistent with the Skill's declared functionality when the user intentionally selects Supabase. Therefore, the network operation is not inher ...[truncated 1656 chars]- Remediation
View remediation
