T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/gcal_core.py:491
- Finding
- Calendar mutations execute without enforced user confirmation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gcal_core.py:349-376`, `scripts/gcal_core.py:431-466`, and `scripts/gcal_core.py:491-513` **Vulnerability Type**: Missing authorization-state enforcement for destructive and state-changing operations **Risk Level**: High ### Vulnerable Code ```python # Confirmation check if not confirmed: print(f"\n📅 Create event:") print(f" Title: {summary}") print(f" When: {format_datetime(start)} - {format_datetime(end)}") if location: print(f" Where: {location}") if attendees: print(f" With: {', '.join(attendees)}") # In actual skill use, Clawdbot will handle confirmation # This is for CLI testing try: event = service.events().insert( calendarId=calendar_id, body=event_body, sendUpdates="all" if attendees else "none" ).execute() print(f"✓ Event created: {event.get('htmlLink')}") return _parse_event(event) except Exception as e: print(f"Error creating event: {e}") return None ``` ```python # Confirmation if not confirmed: print(f"\n✏️ Update event: {event.get('summary')}") if summary: print(f" New title: {summary}") if start: print(f" New start: {format_datetime(start)}") if end: print(f" New end: {format_datetime(end)}") try: updated = service.events().update( calendarId=calendar_id, eventId=event_id, body=event ).execute() print(f"✓ Event updated") return _parse_event(updated) except Exception as e: print(f"Error updating event: {e}") return None ``` ```python parsed = _parse_event(event) if not confirmed: print(f"\n🗑️ Delete event:") print(f" Title: {parsed.get('summary')}") print(f" When: {format_datetime(parsed.get('start_dt'))}") print(f"\n ⚠️ This action cannot be undone!") try: service.events().delete( calendarId=calendar_id, eventId=event_id ).execute() ...[truncated 2435 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce confirmation in code rather than relying on agent behavior: ```python if not confirmed: print_event_preview(event) return False ``` 2. Separate preview and mutation into distinct operations: - First retrieve and display the exact target event and proposed change. - Generate a short-lived confirmation identifier bound to the event ID, calendar ID, operation, and proposed values. - Execute only after the user explicitly approves that exact operation. 3. Require `confirmed is True`, not merely a truthy value, before calling `insert()`, `update()`, `delete()`, or `quickAdd()`. 4. Add confirmation support to `quick_add()` and prevent immediate creation by default. 5. Keep `-y` as an explicit automation override, but document its consequences and ensure that omitting it cannot mutate calendar state. 6. Add tests asserting that no Google API mutation method is called when confirmation is absent or false. 7. For attendee-bearing creations or updates, separately confirm that invitation or update emails will be sent. ]]>
