T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:970
- Finding
- Unvalidated Caller-Controlled Escrow Release Amount<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 970-997 **Vulnerability Type**: Missing authorization, amount validation, and idempotency controls in a financial operation **Risk Level**: High ### Vulnerable Code ```python def release_milestone(task: Task, milestone_name: str, amount_usd: float) -> dict: """Release a specific milestone payment from escrow.""" result = execute("release_escrow", { "escrow_id": task.escrow_id, "amount_usd": str(amount_usd), "release_type": "partial", "reason": f"Milestone completed: {milestone_name}", "metadata": { "task_id": task.task_id, "milestone": milestone_name, }, }) # Record the payment as a transaction execute("record_transaction", { "agent_id": ORCHESTRATOR_ID, "type": "milestone_payment", "counterparty_id": task.assigned_worker_id, "amount_usd": str(amount_usd), "metadata": { "task_id": task.task_id, "milestone": milestone_name, "escrow_id": task.escrow_id, }, }) return result ``` ### Technical Analysis The example passes the caller-provided `amount_usd` directly to the authenticated `release_escrow` operation. It does not verify that: - The amount is positive and finite. - The named milestone exists in the escrow agreement. - The milestone has been completed and approved. - The milestone has not already been paid. - The requested amount equals the milestone's authorized amount. - The amount is less than or equal to the remaining escrow balance. - The caller is authorized to approve this milestone. - The request has an idempotency key preventing duplicate releases. The `milestone_name` is also caller-controlled and is used only as descriptive metadata. It is not resolved against an immutable milestone record. The subsequent transaction record does not prevent the release; it merely logs ...[truncated 1488 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not accept the release amount as an unrestricted caller argument. - Load the escrow and milestone from an authoritative, immutable data store and derive the permitted amount from that record. - Require the milestone to be in an approved and unpaid state before release. - Validate that the amount is finite, positive, and no greater than both the authorized milestone amount and remaining escrow balance. - Introduce a unique idempotency key based on the escrow and milestone IDs. - Perform approval-state transition, release reservation, and payment submission atomically where possible. - Require human approval or multi-party authorization for releases above a configured threshold. - Reconcile the remote escrow response before recording the payment as successful. - Treat remote API validation as defense in depth rather than as a replacement for local authorization controls. ]]>
