T09 · Insecure Skill Coding Practices
- Location
scripts/_pending.py:64- Finding
Local Confirmation Token Does Not Prove Human Approval
- Content
View full analysis
tuple[str, str]: """Create a new pending record. Returns (id, confirmation_token).""" _ensure_dirs() if ttl_seconds is None: ttl_seconds = TRADE_TTL_SECONDS if kind == "trade" else GRID_TTL_SECONDS pid = new_id() token = _new_token() record = { "id": pid, "confirmation_token": token, "kind": kind, "payload": payload, "created_at": now_iso(), "expires_at_epoch": int(time.time()) + ttl_seconds, } path = _path(pid) path.write_text(json.dumps(record, indent=2)) os.chmod(path, 0o600) return pid, token ``` The trade execution path then accepts possession of that token as authorization: ```python try: record = load_pending(args.id) validate_token(record, args.confirmation_token) except PendingError as e: print(f"REFUSED: {e}", file=sys.stderr) return 3 if record.get("kind") != "trade": print(f"REFUSED: proposal {args.id} is kind={record.get('kind')!r}, not 'trade'", file=sys.stderr) return 3 payload = record["payload"] api_params = payload["api_params"] try: check_all(payload["instId"], float(payload["notional_usdt"])) except GuardrailError as e: print(f"REFUSED at execute time: {e}", file=sys.stderr) return 3 resp = trade_api().place_order(**api_params) ``` ### Technical Analysis The confirmation token proves only that the caller can read the local pending file. It does not prove that the user sent the documented `YES ` response. The Skill instructions explicitly direct the Agent to read that same pending file to obtain the token. Consequently, the proposing ...[truncated 1465 chars]- Remediation
View remediation
` from the correct user and conversation. 3. Bind approval to: - Proposal ID - Authenticated user and account - Conversation or session ID - Immutable hash of the complete order payload - Creation and expiration timestamps 4. Have execution atomically consume server-side approval state rather than accepting a bearer token readable by the Agent. 5. Prevent the proposal process from writing or reading approval credentials. 6. Preserve single-use and expiry protections, but treat them as replay defenses rather than proof of human consent. 7. Log the authenticated approval event and consumed payload hash for later audit. ]]>
