T09 · Insecure Skill Coding Practices
- Location
EXAMPLES.md:678- Finding
Budget Reallocation Proceeds Without Runtime User Approval
- Content
View full analysis
Vulnerability Details
File Location:
EXAMPLES.md, lines 678–698
Vulnerability Type: Missing authorization for a financially consequential operation
Risk Level: Highjavascript // 5. Implement optimization (if approved) const shouldOptimize = true; // Get user approval in real scenario if (shouldOptimize) { await testAgent.updateMediaBuy({ media_buy_id: mediaBuyId, updates: { package_updates: [ { package_id: best.package_id, budget_change: 5000 // Add $5k }, { package_id: worst.package_id, budget_change: -5000 // Remove $5k } ] } }); console.log('✅ Budget reallocation complete'); }Technical Analysis
The example states that optimization should occur only after approval, but
shouldOptimizeis hardcoded totrue. Consequently, the approval condition does not enforce authorization and the call toupdateMediaBuyalways proceeds whenever the performance-ratio condition is met.Although the example uses
testAgent, the project describes these examples as adaptable and separately instructs users to switch to production agent endpoints and credentials. If copied into a production workflow, this pattern can authorize a financially consequential campaign update without transaction-specific user consent.The decision also depends on remotely supplied delivery metrics and a simplistic efficiency calculation. Incorrect, incomplete, stale, or manipulated metrics could therefore trigger an inappropriate allocation change.
Attack Path
- An operator adapts the documented optimization example for a production AdCP client.
- The client retrieves package-level campaign delivery metrics.
- The code ranks packages and identifies the highest- and lowest-efficiency packages.
- When the efficiency ratio exceeds two, the code reaches the nominal approval check.
- Because
shouldOptimizeis alwaystrue, no actual user confirmation ...[truncated 752 chars]
- Remediation
View remediation
Remediation Suggestions
- Replace the hardcoded flag with a real, transaction-specific approval result that defaults to denial:
javascript const approved = await requestExplicitApproval({ environment: agentEnvironment, media_buy_id: mediaBuyId, changes: [ { package_id: best.package_id, budget_change: 5000 }, { package_id: worst.package_id, budget_change: -5000 } ] }); if (!approved) { return { status: 'cancelled' }; }- Immediately before approval, display the environment, endpoint, campaign ID, affected package IDs, current and proposed budgets, total spend impact, and effective time.
- Require fresh approval for every production update; do not reuse consent from campaign creation or an earlier recommendation.
- Separate recommendation generation from mutation execution so analysis cannot directly trigger a financial action.
- Add a dry-run mode and make it the default outside explicitly configured production execution.
- Enforce per-operation and cumulative adjustment limits.
- Re-fetch campaign state after approval and reject the operation if budgets, package identities, metrics, or campaign status changed.
- Use idempotency keys to prevent duplicate reallocations during retries.
- Validate that all target packages belong to the intended media buy and authenticated account.
- Record the approving identity, proposed change, timestamp, endpoint, response, and resulting campaign state in an audit log.
- Clearly distinguish test-only code from production-safe examples and include a warning that replacing
testAgentwith a production client requires an approval control.
