T09 · Insecure Skill Coding Practices
- Location
veto_skill.py:42- Finding
Unbounded HTTP Requests and Polling Can Block the Agent Indefinitely
- Content
View full analysis
Vulnerability Details
File Location:
veto_skill.py, lines 42–69
Vulnerability Type: Missing network timeouts and approval deadline
Risk Level: MediumVulnerable Code
python response = requests.post(f"{BASE_URL}/request", json=payload) if response.status_code == 401: print("Error: Invalid VetoAPI key.") return False response.raise_for_status() request_id = response.json().get("request_id") print(f"Approval email sent to {user_email}.") print(f"Waiting for decision (Request ID: {request_id})...") while True: poll = requests.get(f"{BASE_URL}/request/{request_id}") poll.raise_for_status() status = poll.json().get("status") if status == "approved": print("\n[APPROVED] Human gave the green light. Proceeding...") return True elif status == "rejected": print("\n[REJECTED] Human denied the request. Aborting.") return False sys.stdout.write(".") sys.stdout.flush() time.sleep(5)Technical Analysis
Both
requests.post()andrequests.get()are called without connect or read timeouts. A remote endpoint or intermediary can therefore leave a connection open without producing a complete response, causing the calling thread to wait indefinitely.The approval loop is also unconditional and has no overall deadline, attempt limit, or handling for unexpected terminal states. If the service continually returns a pending or unknown status, the function never returns. In addition,
request_idis extracted without validation. A successful response that omits this field causes the code to poll/request/None, which may also remain in a nonterminal state.Although request exceptions are caught elsewhere in the function, no exception is raised me ...[truncated 946 chars]
- Remediation
View remediation
Remediation Suggestions
- Set explicit connect and read timeouts on every request, for example:
python timeout = (5, 15) response = requests.post( f"{BASE_URL}/request", json=payload, timeout=timeout, ) - Apply the same timeout policy to polling requests.
- Enforce a configurable overall approval deadline using a monotonic clock.
- Set a maximum number of polling attempts and fail closed when it is exceeded.
- Validate that
request_idis a nonempty string before beginning polling. - Reject unknown or malformed response statuses rather than polling forever.
- Catch timeout exceptions explicitly and return
Falsewith an appropriate diagnostic. - Consider accepting a cancellation signal so callers can terminate approval waits cleanly.
- Set explicit connect and read timeouts on every request, for example:
