T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/fetch-with-aging.js:25
- Finding
- GraphQL Injection Through an Unvalidated Gotchi Identifier<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch-with-aging.js:25-34`, with attacker-controlled input entering the call at `scripts/fetch-with-aging.js:123-124` **Vulnerability Type**: GraphQL injection caused by direct string interpolation **Risk Level**: Medium ### Vulnerable Code ```js async function querySubgraph(gotchiId) { const query = `{ aavegotchi(id: "${gotchiId}") { id name createdAt claimedAt hauntId baseRarityScore modifiedRarityScore } }`; ``` The value is obtained directly from the command line and passed to the vulnerable query construction: ```js const tokenId = process.argv[2] || '1484'; fetchGotchiWithAging(tokenId) ``` It reaches the network request through: ```js const subgraphData = await querySubgraph(tokenId); ``` ### Technical Analysis The command-line value is inserted directly inside a quoted GraphQL argument. The script does not verify that `tokenId` contains only digits, nor does it use typed GraphQL variables. A crafted value containing quotation marks and GraphQL syntax can terminate the intended `id` string and modify the query document sent to the configured Goldsky endpoint. This differs from the primary `fetch-gotchi.js` implementation, which validates its token ID as numeric. Although the endpoint exposes public blockchain information, the flaw permits callers to make the Skill issue queries beyond its intended single-token lookup behavior. ### Attack Path 1. An attacker or untrusted caller supplies a specially constructed command-line argument instead of a numeric Gotchi ID. 2. The value is assigned to `tokenId` without validation. 3. `querySubgraph()` interpolates the value into the GraphQL document. 4. The modified document is sent in an HTTPS POST request to `api.goldsky.com`. 5. If accepted by the GraphQL parser, the injected selection or additional query operation is processed by the remote service. ### Impact Assessment Successful ex ...[truncated 488 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Validate the CLI argument before making any request: ```js const tokenId = process.argv[2]; if (!tokenId || !/^\d+$/.test(tokenId)) { console.error('Usage: node fetch-with-aging.js <numeric-token-id>'); process.exit(1); } ``` 2. Enforce a reasonable numeric range and reject values that cannot be represented safely. 3. Use GraphQL variables rather than constructing the document with interpolation: ```js const query = ` query GetAavegotchi($id: ID!) { aavegotchi(id: $id) { id name createdAt claimedAt hauntId baseRarityScore modifiedRarityScore } } `; const data = JSON.stringify({ query, variables: { id: gotchiId } }); ``` 4. Add request timeouts, response-size limits, HTTP status validation, and GraphQL error handling to reduce denial-of-service exposure. ]]>
