T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/vb.js:5
- Finding
- Unrestricted API Endpoint Override Can Expose Vestaboard Credentials## Vulnerability Details **File Location**: `scripts/vb.js:5`, `scripts/vb.js:72-115` **Vulnerability Type**: Arbitrary credential forwarding through an unvalidated API endpoint **Risk Level**: High ### Vulnerable Code ```js const API_BASE = (process.env.VESTABOARD_API_BASE || 'https://cloud.vestaboard.com/').replace(/\/+$/, '/'); ``` ```js async function vbRead() { const headers = authHeaders(); if (!headers) throw new Error('Missing VESTABOARD_TOKEN (preferred) or VESTABOARD_RW_KEY (legacy)'); const res = await request(API_BASE, { method: 'GET', headers: { ...headers, 'Content-Type': 'application/json' } }); const body = await res.body.text(); if (res.statusCode >= 400) throw new Error(`HTTP ${res.statusCode}: ${body}`); process.stdout.write(body + (body.endsWith('\n') ? '' : '\n')); } async function vbWriteText(text) { const headers = authHeaders(); if (!headers) throw new Error('Missing VESTABOARD_TOKEN (preferred) or VESTABOARD_RW_KEY (legacy)'); const lines = wrapToLines(text); const payload = JSON.stringify({ text: linesToText(lines) }); const res = await request(API_BASE, { method: 'POST', headers: { ...headers, 'Content-Type': 'application/json' }, body: payload }); const body = await res.body.text(); if (res.statusCode >= 400) throw new Error(`HTTP ${res.statusCode}: ${body}`); process.stdout.write(body + (body.endsWith('\n') ? '' : '\n')); } async function vbWriteLayout(path) { const headers = authHeaders(); if (!headers) throw new Error('Missing VESTABOARD_TOKEN (preferred) or VESTABOARD_RW_KEY (legacy)'); const raw = readFileSync(path, 'utf8'); const layout = JSON.parse(raw); const payload = JSON.stringify(layout); const res = await request(API_BASE, { method: 'POST', headers: { ...headers, 'Content-Type': 'application/json' }, body: payload ...[truncated 2326 chars]
- Remediation
- ## Remediation Suggestions 1. Remove `VESTABOARD_API_BASE` configurability unless custom endpoints are an explicit operational requirement. 2. If endpoint selection is required, parse the value with `new URL()` and require the `https:` protocol. 3. Allowlist only documented Vestaboard hosts, such as the official Cloud API host and any explicitly supported legacy host. 4. Reject URLs containing embedded user information, unexpected ports, fragments, or unapproved hostnames. 5. Disable or strictly validate redirects so authentication headers cannot be forwarded to another origin. 6. Keep cloud and legacy endpoint selection explicit and bind each authentication-header type to its intended trusted hostname. 7. Fail closed when endpoint validation fails, before constructing or transmitting authentication headers. 8. Validate layout input as exactly six arrays of twenty-two permitted integer character codes before transmission. This does not resolve credential forwarding, but it limits malformed or unintended data disclosure. 9. Add automated tests confirming that HTTP URLs, unknown hosts, alternate ports, and redirect-based origin changes are rejected.
