T09 · Insecure Skill Coding Practices
Warning
- Location
- src/mock-runtime.js:343
- Finding
- Unenforced Input Limits Permit Excessive Paid Generation and Polling## Vulnerability Details **File Location**: `src/mock-runtime.js:343-352`, `src/mock-runtime.js:382-389`, and `src/mock-runtime.js:409-416` **Vulnerability Type**: Missing runtime input validation and resource-consumption controls **Risk Level**: Medium The tool schema declares limits for security-sensitive and cost-sensitive fields in `src/tools.json:91-101`, including a maximum image count of 4, a maximum of 10 polling attempts, and a polling interval between 200 and 10,000 milliseconds. The executable runtime does not validate parsed input against this schema. **Vulnerable code:** ```javascript const body = { request_id: requestId, model, prompt: input.prompt, product: 'image', units: { count: input.count || 1, resolution: input.resolution || '1K', aspect_ratio: input.aspect_ratio || '1:1' }, scene: input.scene || 'text-to-image' }; ``` ```javascript const attempts = input.poll_attempts || 3; const intervalMs = input.poll_interval_ms || 1500; let lastPoll = null; for (let i = 0; i < attempts; i++) { await sleep(intervalMs); lastPoll = await pollImageResult({ request_id: requestId }); if (!lastPoll.ok) return { ...out, auto_poll: true, poll_error: lastPoll }; if (!lastPoll.pending) { return { ...out, auto_poll: true, final_result: lastPoll }; } } ``` ```javascript async function main() { const [,, toolName, rawInput] = process.argv; if (!toolName) { console.error('Usage: node src/mock-runtime.js <tool_name> <json_input>'); process.exit(1); } const input = rawInput ? JSON.parse(rawInput) : {}; let result; if (toolName === 'rewrite_image_prompt') result = rewritePrompt(input); else if (toolName === 'estimate_image_cost') result = await estimateCost(input); else if (toolName === 'generate_image') result = await generateImage(input); else if (toolName === 'poll_image_result') result = awai ...[truncated 2889 chars]
- Remediation
- ## Remediation Suggestions 1. Validate every invocation against the corresponding schema in `src/tools.json` before dispatch. Use a maintained JSON Schema validator or equivalent explicit validation. 2. Reject unknown properties and enforce all declared types, required fields, enumerations, and numeric ranges. 3. Add independent defensive checks inside `generateImage()`: - Require `count` to be an integer from 1 through 4. - Require `poll_attempts` to be an integer from 1 through 10. - Require `poll_interval_ms` to be an integer from 200 through 10,000. - Allow only supported resolutions, aspect ratios, quality modes, scenes, and models. 4. Do not silently clamp cost-sensitive values unless the caller is explicitly informed. Prefer rejecting invalid paid-operation requests before any network call. 5. Add an account-level or invocation-level credit budget and require explicit approval when a request exceeds it. 6. Add request timeouts, an overall auto-poll deadline, and cancellation support so polling cannot retain the process indefinitely. 7. Add regression tests that invoke the executable entry point with boundary, oversized, negative, fractional, and wrong-type values, verifying that no live request is made when validation fails. 8. Keep server-side limits on the Rynjer API because client-side validation alone cannot protect the service from modified clients.
