T09 · Insecure Skill Coding Practices
- Location
scripts/wait_for_video.js:6- Finding
Unbounded Video Polling Can Cause Resource Exhaustion
- Content
View full analysis
Vulnerability Details
File Location:
scripts/wait_for_video.js, lines 6–19
Vulnerability Type: Improper validation and bounding of user-controlled polling parameters
Risk Level: MediumVulnerable Code
js const maxWait = Number(input.max_wait_time || 300000); const poll = Number(input.poll_interval || 5000); const start = Date.now(); while (Date.now() - start < maxWait) { const data = await getJson(`/paas/v4/async-result/${input.task_id}`); const status = data.task_status; if (status === 'SUCCESS') { return print({ success: true, action: 'wait_for_video', task_id: input.task_id, data }); } if (status === 'FAIL') { throw new Error(data.error || 'video generation failed'); } await sleep(poll); }Technical Analysis
The script converts the attacker-controlled
max_wait_timeandpoll_intervalvalues withNumber()but does not verify that they are finite, positive, or within safe limits.A value such as
"Infinity"formax_wait_timemakes the loop's time condition remain true indefinitely. A negative value forpoll_intervalis passed tosetTimeoutthroughsleep()and effectively results in little or no delay. Combined, these values can cause the process to issue authenticated polling requests continuously until the task succeeds, fails, or the process is externally terminated.The script also lacks a maximum request count, cancellation mechanism, and network request timeout, compounding the availability risk.
Attack Path
-
An attacker or untrusted caller invokes
wait_for_video.jswith an existing or long-running video task ID. -
The caller supplies a payload such as:
json { "task_id": "valid-pending-task-id", "max_wait_time": "Infinity", "poll_interval": -1 } -
Number("Infinity")evaluates to positive infinity, while the negative polling interval produces an effectively immediate timer. -
The loop repeatedly calls the Zhipu asynchronous-result e ...[truncated 768 chars]
-
- Remediation
View remediation
Remediation Suggestions
Validate both parameters before entering the polling loop:
- Require numeric, finite, integer values using
Number.isFinite()andNumber.isInteger(). - Reject non-positive values rather than silently coercing them.
- Enforce explicit limits, for example:
poll_interval: 1,000–30,000 milliseconds.max_wait_time: 1,000–900,000 milliseconds.
- Add a maximum polling-attempt count independent of elapsed time.
- Add a timeout to each HTTPS request so a stalled connection cannot hold the process indefinitely.
- Support cancellation through an
AbortControlleror equivalent mechanism. - Consider applying exponential backoff with a maximum delay.
Example validation:
js const maxWait = Number(input.max_wait_time ?? 300000); const poll = Number(input.poll_interval ?? 5000); if (!Number.isFinite(maxWait) || !Number.isInteger(maxWait) || maxWait < 1000 || maxWait > 900000) { throw new Error('max_wait_time must be an integer between 1000 and 900000'); } if (!Number.isFinite(poll) || !Number.isInteger(poll) || poll < 1000 || poll > 30000) { throw new Error('poll_interval must be an integer between 1000 and 30000'); } const maxAttempts = Math.ceil(maxWait / poll); for (let attempt = 0; attempt < maxAttempts; attempt++) { // Query status and stop on success or failure. await sleep(poll); }- Require numeric, finite, integer values using
