T09 · Insecure Skill Coding Practices
- Location
scripts/patentmax_client.py:914- Finding
Metered API Operations Can Execute Without an Enforced User-Approved Spending Limit
- Content
View full analysis
Vulnerability Details
File Location:
scripts/patentmax_client.py:789-790, 809, 914-920, 1265-1268; related workflow instructions atSKILL.md:143,352
Vulnerability Type: Missing authorization control for financially consequential operations
Risk Level: MediumRelevant Code
python # No configured budget means monetary spending is not blocked. # The original source comment at lines 789-790 documents this behavior. BILLED_COMMANDS = ( "search", "stats", "company", "brief", "similar", "citation", "figure" ) def enforce_budget(args): enforce_search_budget(args) session = _load_session() if not session or args.command not in BILLED_COMMANDS: return limit = float(session.get("limit", 0)) spent = float(session.get("spent", 0)) need = estimate_cost(args) if limit <= 0 or spent + need <= limit + 1e-9: returnpython enforce_budget(args) if args.command in BILLED_COMMANDS: _task_id = ensure_task() result = args.func(args) if args.command in BILLED_COMMANDS: record_usage(args.command)The associated Skill workflow is internally inconsistent:
SKILL.md:143says the depth and estimated cost should be shown before paid searching begins.SKILL.md:352instructs the Agent to execute estimated costs of up to ¥5 silently and report the charge afterward.
Technical Analysis
The client identifies financially consequential operations through
BILLED_COMMANDS, but does not require a user-approved budget before executing them.enforce_budget()returns without blocking when:- No active budget session exists; or
- The session has a limit of zero or less.
Execution then continues directly to
args.func(args), which can issue an authenticated, metered API request. The budget session subsequently created byensure_task()has no monetary limit by default. Therefore, the control records usage after execution but does not establish prior financial authorization....[truncated 2457 chars]
- Remediation
View remediation
Remediation Suggestions
-
Require prior authorization for every billable command. Reject execution unless the current task has an explicitly initialized spending limit or a verifiable approval token.
-
Use fail-closed budget logic. Replace the permissive behavior for missing or non-positive limits with an error that identifies the command and estimated maximum charge:
python if args.command in BILLED_COMMANDS: if not session or float(session.get("limit", 0)) <= 0: die( "This operation is billable and requires an approved task budget.", exit_code=3 )-
Bind approval to the current task. Store the approved amount, authorized command classes, account context, and task identifier together. Do not reuse approval across unrelated or expired tasks.
-
Enforce the cap before network access. Reserve the estimated charge atomically before calling the API, then reconcile it against the authoritative charge returned by the service. Prevent concurrent processes from independently passing the same remaining-budget check.
-
Cover all billable operations. Add operation-count or monetary controls for
stats,company,brief,similar,citation, andfigure, not onlysearch. -
Remove the silent-spending instruction. Make
SKILL.mdconsistently require disclosure and explicit approval before any operation that can consume paid balance. Free-quota execution may be handled separately only when the client can authoritatively verify that the request will not incur a charge. -
Require renewed approval when scope changes. Additional rounds, higher-cost operations, or execution beyond the approved amount should stop and request a new authorization rather than silently continuing.
-
