T09 · Insecure Skill Coding Practices
- Location
scripts/tx.mjs:38- Finding
Add/drop transactions can execute without enforced user approval
- Content
View full analysis
Vulnerability Details
File Location:
scripts/tx.mjs:38-47
Vulnerability Type: Missing authorization gate for consequential roster transactions
Risk Level: MediumComplete Code Snippet
js // Add a player, drop another (pair them — a bare ADD fails if the roster is full). export async function addDrop({ season, leagueId, teamId, addId, dropId, week }) { const items = [{ playerId: addId, type: 'ADD', toTeamId: teamId }]; if (dropId) items.push({ playerId: dropId, type: 'DROP', fromTeamId: teamId }); return post(txUrl(season, leagueId), { isLeagueManager: false, teamId, type: 'FREEAGENT', scoringPeriodId: week, executionType: 'EXECUTE', items, }, 'addDrop'); }Technical Analysis
The Skill's documented authorization model requires add/drop actions to be proposed and approved by the user. Specifically,
references/strategy.md:24-38states that waiver adds and drops follow a “propose → approve” workflow.The exported
addDropfunction does not technically enforce that policy. When called with valid transaction identifiers, it constructs aFREEAGENTtransaction withexecutionType: 'EXECUTE'and immediately submits it through the authenticated ESPN API path. It has no approval token, confirmation parameter, interactive prompt, or dry-run default.The caller controls
season,leagueId,teamId,addId,dropId, andweek. Therefore, an Agent invocation caused by erroneous reasoning, manipulated contextual input, or another direct module caller can bypass the documented human-approval boundary. The stored ESPN cookies provide the authority needed to apply the transaction.This is a reachable authorization-control weakness, but the reviewed project does not provide evidence that its author intended to abuse it.
Attack Path
- The user authenticates through the Skill, producing reusable ESPN session cookies.
- An Agent or another local caller imports
addDropfromscripts/tx.mjs. - The caller supplie ...[truncated 876 chars]
- Remediation
View remediation
Remediation Suggestions
- Make add/drop operations dry-run-only by default and return the complete proposed transaction without sending it.
- Require an explicit execution flag and a validated approval artifact tied to the exact league, team, week, add-player ID, and drop-player ID.
- Generate the approval artifact only after displaying the full transaction to the user and receiving affirmative confirmation.
- Reject stale, reused, or mismatched approvals.
- Keep the approval check inside the executable helper so direct module calls cannot bypass it.
- Re-read the roster immediately before execution and verify that the target team, player IDs, and roster state still match the approved proposal.
- Record the approval, finalized request, response status, and transaction identifier in an audit log without recording authentication cookies.
