Back to skill

Security audit

gcal-pro - Google Calendar

Security checks for vulnerabilities and agentic risk

Overview

This is a real Google Calendar skill, but it needs review because its code can change or delete calendar events even when confirmation was not actually provided.

Review before installing. Use this only if you are comfortable granting Google Calendar access, and avoid Pro write operations until confirmation enforcement is fixed. Keep client_secret.json and token.json private, do not print or share them, and consider installing dependencies in an isolated environment with reviewed or pinned versions.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

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. ]]>

other

Warning
Location
scripts/gcal_license.py:20
Finding
Unnecessary hostname and username collection creates a persistent machine fingerprint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gcal_license.py:20-29` and `scripts/gcal_license.py:71-77` **Vulnerability Type**: Unnecessary environment reconnaissance and device fingerprinting **Risk Level**: Medium ### Vulnerable Code ```python def get_machine_id() -> str: """Generate a machine-specific identifier.""" # Combine hostname and username for basic machine ID import socket hostname = socket.gethostname() username = os.environ.get("USERNAME") or os.environ.get("USER") or "unknown" raw = f"{hostname}:{username}" return hashlib.sha256(raw.encode()).hexdigest()[:16] ``` ```python # Create license file license_data = { "key": key.upper().strip(), "tier": "pro", "valid": True, "activated_at": datetime.utcnow().isoformat(), "machine_id": get_machine_id() } ``` ### Technical Analysis License activation reads the local hostname and operating-system username, combines them, computes a truncated SHA-256 digest, and stores the resulting stable identifier in `~/.config/gcal-pro/license.json`. This qualifies as limited environment reconnaissance because the skill inspects host and account identity data unrelated to Google Calendar functionality. The collection also exceeds the minimum needs of the current license implementation: `machine_id` is written but never checked by `validate_license_key()`, `get_license_info()`, or `is_pro()`. Hashing does not make the identifier anonymous. Hostnames and usernames often have low entropy and can be guessed or correlated, while truncating the digest to 16 hexadecimal characters does not prevent dictionary testing. The setup and privacy documentation do not disclose this collection. No code was found that transmits the hostname, username, or machine identifier to a remote endpoint. The current impact is therefore local collection and persistent fingerprinting, not confirmed network exfiltration. ### Attack Path 1. A user runs license activation: ```b ...[truncated 1065 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `get_machine_id()` and omit `machine_id` from the license file because the current implementation does not use it. 2. If an installation identifier is genuinely required, generate a random UUID locally rather than deriving it from hostname or username: ```python import uuid installation_id = str(uuid.uuid4()) ``` 3. Do not collect raw or derived host identity unless device binding is necessary and proportionate. 4. If device binding is introduced: - Clearly disclose what is collected and why. - Obtain informed user consent. - Define retention and deletion behavior. - Avoid reversible or low-entropy identifiers. - Transmit data only over authenticated TLS to a documented licensing endpoint. - Permit users to inspect and deactivate bound devices. 5. Add a migration that removes the unused `machine_id` field from existing license files. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:2
Finding
Open-ended dependency versions permit unreviewed supply-chain changes<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:2-7` **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Medium ### Vulnerable Code ```text google-auth>=2.23.0 google-auth-oauthlib>=1.1.0 google-auth-httplib2>=0.1.1 google-api-python-client>=2.100.0 pytz>=2023.3 python-dateutil>=2.8.2 ``` The installation documentation directs users to execute: ```text pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses an open-ended minimum version constraint. Installation can therefore resolve to any later release available from the configured Python package index. There is no lock file, upper bound, hash verification, or reproducible dependency set. The package names are consistent with the declared Google Calendar functionality, and no currently listed package was established to be malicious during this static audit. The vulnerability is that future installation behavior can change after review without any modification to the skill package. This is especially relevant because the dependencies run in a process that reads OAuth client credentials and refresh tokens and accesses private calendar data. ### Attack Path 1. A user follows the installation guide and runs `pip install -r requirements.txt`. 2. `pip` resolves the newest versions satisfying the `>=` constraints at installation time. 3. A compromised upstream release, package-index compromise, malicious mirror, or unexpectedly incompatible future release is selected. 4. Third-party code executes during installation or when imported by the skill. 5. That code runs with the user's local process privileges and may access files and data available to the calendar process. This is a conditional supply-chain path; the audit did not identify a presently malicious dependency. ### Impact Assessment A compromised or unsafe resolved dependency could potentially access: - `~/.config/gcal-pro/client_secret.json` - `~/.config/gcal-pro/token.json`, ...[truncated 456 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin dependencies to reviewed versions rather than using open-ended minimum constraints. 2. Generate and commit a reproducible lock file using a tool such as `pip-tools`, Poetry, or uv. 3. Require package hashes during installation, for example through a generated requirements file used with: ```bash pip install --require-hashes -r requirements.lock ``` 4. Review transitive dependencies, not only the six direct dependencies. 5. Use automated vulnerability and update monitoring, but require review and testing before changing locked versions. 6. Install into an isolated virtual environment with the minimum necessary operating-system privileges. 7. Prefer a trusted package index and avoid untrusted mirrors or additional indexes that could introduce dependency-confusion risk. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (53)

Credential Access

High
Category
Privilege Escalation
Content
| File | Purpose |
|------|---------|
| `client_secret.json` | OAuth app credentials (you provide) |
| `token.json` | Your access token (auto-generated) |
| `license.json` | Pro license (if purchased) |

## Clawdbot Integration
Confidence
78% confidence
Finding
The README states that `token.json` stores the user's access token but does not warn that possession of this file may allow calendar access. In the context of a skill handling personal scheduling data, failing to treat persisted tokens as sensitive secrets can lead to accidental exposure through weak file permissions, backups, or shared systems.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented behavior says this is a Google Calendar skill, but the detected implementation reportedly performs licensing and machine-identification functions while lacking actual calendar functionality. That mismatch is a strong trust-boundary violation: users or calling agents may grant calendar-related privileges while the skill instead handles local identifiers and license state, suggesting hidden or undeclared behavior.

Credential Access

High
Category
Privilege Escalation
Content
```
~/.config/gcal-pro/
├── client_secret.json   # OAuth app credentials (user provides)
├── token.json           # User's access token (auto-generated)
└── license.json         # Pro license (if purchased)
```
Confidence
74% confidence
Finding
The documented file layout stores OAuth client credentials, access tokens, and license data together under a predictable path in the user's home directory. In an agent environment that also uses file_read/file_write capabilities, predictable plaintext storage increases the risk of accidental disclosure, overbroad access by other skills, or token theft if local files are exposed.

Credential Access

High
Category
Privilege Escalation
Content
```
~/.config/gcal-pro/
├── client_secret.json   # OAuth app credentials (user provides)
├── token.json           # User's access token (auto-generated)
└── license.json         # Pro license (if purchased)
```
Confidence
86% confidence
Finding
The documentation explicitly indicates persistent local storage of a user's access token in token.json. Access tokens can authorize calendar access without re-prompting the user, so theft of this file could enable unauthorized reading or modification of calendar data depending on granted scopes.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Google Cloud Project Setup Guide

## Overview
This guide walks you through creating a Google Cloud project, enabling the Calendar API, and configuring OAuth 2.0 to get your `client_secret.json` file.

**Time required:** ~15 minutes  
**Prerequisites:** Google account
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\gcal-pro"

# Move the downloaded file (adjust source path as needed)
Move-Item "$env:USERPROFILE\Downloads\client_secret*.json" "$env:USERPROFILE\.config\gcal-pro\client_secret.json"

# Verify
Get-Content "$env:USERPROFILE\.config\gcal-pro\client_secret.json" | Select-Object -First 3
Confidence
94% confidence
Finding
This section not only moves a sensitive credential file into a persistent config directory but also immediately instructs the user to print its contents for verification. The dangerous part is the exposure path, which can leak OAuth client secrets through terminal history, logs, screenshots, or recorded sessions.

Credential Access

High
Category
Privilege Escalation
Content
Move-Item "$env:USERPROFILE\Downloads\client_secret*.json" "$env:USERPROFILE\.config\gcal-pro\client_secret.json"

# Verify
Get-Content "$env:USERPROFILE\.config\gcal-pro\client_secret.json" | Select-Object -First 3
```

**macOS/Linux:**
Confidence
95% confidence
Finding
`Get-Content ... | Select-Object -First 3` deliberately reveals the beginning of the secret-bearing OAuth credentials file in the terminal. That creates an unnecessary credential exposure channel and is inconsistent with the document's later warning not to share these files.

Credential Access

High
Category
Privilege Escalation
Content
mv ~/Downloads/client_secret*.json ~/.config/gcal-pro/client_secret.json

# Verify
head -3 ~/.config/gcal-pro/client_secret.json
```

---
Confidence
95% confidence
Finding
`head -3 ~/.config/gcal-pro/client_secret.json` exposes the contents of a sensitive OAuth credential file to the terminal. This creates avoidable leakage risk through shell history, shared terminals, support captures, and screenshots.

Credential Access

High
Category
Privilege Escalation
Content
⚠️ **NEVER commit these files to git:**
- `client_secret.json` — Your app's credentials
- `token.json` — User's access tokens

Add to `.gitignore`:
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.