T09 · Insecure Skill Coding Practices
- Location
scripts/walk-next-game.mjs:34- Finding
Unvalidated Persisted Draft URL Enables Server-Side Request Forgery
- Content
View full analysis
{ try { const payload = await readJson(picksPath); return { draftToken: payload?.draftToken ?? null, draftApiUrl: payload?.draftApiUrl ?? null }; } catch { return { draftToken: null, draftApiUrl: null }; } }; ``` `scripts/walk-next-game.mjs:34-37` issues a GET request to that URL: ```js if (meta.draftToken && meta.draftApiUrl) { try { const res = await fetch(meta.draftApiUrl); if (res.ok) { ``` `scripts/walk-apply-pick.mjs:49-55` issues a PATCH request and transmits bracket state to that URL: ```js if (meta.draftToken && meta.draftApiUrl) { try { await fetch(meta.draftApiUrl, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ matchIndex: applied.gameIndex, winnerSeed }), }); ``` ### Technical Analysis The `draftApiUrl` value is loaded from a local picks-state JSON file. The CLI permits the picks file to be selected by the caller, and the metadata reader does not verify the URL's protocol, hostname, port, path, credentials, resolved IP address, or relationship to the configured BracketsBot frontend. Both `walk-next` and `walk-apply` subsequently pass this persisted value directly to `fetch()`. Consequently, anyone able to supply or modify a picks file can direct the process to send requests to arbitrary destinations, including: - Internet hosts controlled by an attacker - Loopback services such as `127.0.0.1` - Private-network services - Link-local or cloud metadata endpoints - Services reacha ...[truncated 1899 chars]- Remediation
View remediation
