Back to skill

Security audit

gcal-pro - Google Calendar

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real Google Calendar integration, but its write operations can create, change, or delete calendar events even when confirmation is not actually enforced.

Review carefully before installing. Only use it if you are comfortable granting Google Calendar access, and do not rely on its current confirmation flag to protect against unintended creates, edits, or deletions. Avoid pasting or displaying OAuth credential files in chats or logs, and consider testing with a non-critical calendar first.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/gcal_core.py:337
Finding
Calendar Mutations Execute Without Enforced User Confirmation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gcal_core.py:337-353`, `scripts/gcal_core.py:381-384`, `scripts/gcal_core.py:457-472`, and `scripts/gcal_core.py:515-525` **Vulnerability Type**: Fail-open authorization and confirmation control **Risk Level**: High ### Vulnerable Code Event creation: ```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() ``` Quick-add creation: ```python try: event = service.events().quickAdd( calendarId=calendar_id, text=text ).execute() ``` Event update: ```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() ``` Event deletion: ```python 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() ``` ### Technical Analysis The `confirmed` argument is presented as a safety control, but setting it to `False` only causes event details or a warni ...[truncated 2113 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make all mutation methods fail closed when confirmation has not been supplied: ```python if not confirmed: display_proposed_change(...) return None ``` For deletion, return `False` rather than continuing. 2. Add an explicit confirmation parameter to `quick_add()` and prevent the API request unless it is true. 3. Prefer a two-phase transaction: - Phase one prepares and displays the exact mutation. - Phase two accepts a short-lived confirmation token tied to the operation, event ID, calendar ID, and proposed values. 4. Do not treat a generic prior confirmation as authorization for a later or modified request. 5. Require fresh confirmation when the selected event, time, attendees, or other material fields change. 6. Add unit tests using a mocked Calendar API to verify that `insert()`, `quickAdd()`, `update()`, and `delete()` are never called when confirmation is absent or false. 7. Consider using `sendUpdates="none"` by default and separately confirm operations that send invitations or notifications. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/gcal_license.py:32
Finding
Any Well-Formed License Key Grants Pro Write Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gcal_license.py:32-52` and `scripts/gcal_license.py:61-80` **Vulnerability Type**: Client-side authorization bypass **Risk Level**: Medium ### Vulnerable Code ```python def validate_license_key(key: str) -> bool: """ Validate a license key format. Real implementation would verify against Gumroad API or similar. For MVP, we use a simple checksum validation. """ if not key: return False # Expected format: GCAL-XXXX-XXXX-XXXX parts = key.upper().strip().split("-") if len(parts) != 4 or parts[0] != "GCAL": return False # Simple checksum: last 4 chars should be based on first 3 parts check_input = "-".join(parts[:3]) expected_check = hashlib.md5(check_input.encode()).hexdigest()[:4].upper() # For now, accept any well-formed key (implement real validation later) # In production: verify against Gumroad API return all(len(p) == 4 for p in parts[1:]) ``` The accepted key is then converted directly into a trusted local authorization record: ```python # Create license file license_data = { "key": key.upper().strip(), "tier": "pro", "valid": True, "activated_at": datetime.utcnow().isoformat(), "machine_id": get_machine_id() } try: with open(LICENSE_FILE, "w") as f: json.dump(license_data, f, indent=2) ``` ### Technical Analysis The function computes `expected_check` but never compares it with the supplied key. Instead, it accepts any value with the prefix `GCAL` and three four-character components. After this format-only check succeeds, `activate_license()` writes `"tier": "pro"` and `"valid": true` to a locally controlled JSON file. `is_pro()` subsequently trusts these fields, and `gcal_auth.py` uses the result when choosing OAuth scopes. Therefore, the license check is an ineffective access-control boundary rather than a genuine validation mechanism. The local file is als ...[truncated 1312 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace format-only validation with one of the following: - Server-side entitlement validation over authenticated HTTPS. - Offline licenses signed with a vendor private key and verified using an embedded public key. 2. If server validation is used, validate the product, purchaser, entitlement status, activation limits, and expiration rather than accepting a generic success flag. 3. Do not rely on mutable fields such as `"valid": true` in a user-controlled JSON file as proof of authorization. 4. If offline signed licenses are used, include the license tier, customer identifier, validity period, and optional machine binding inside the signed payload. 5. Remove the unused MD5 checksum code. A non-secret checksum is not suitable as an authorization mechanism because users can reproduce it. 6. Keep licensing separate from OAuth least privilege. Request write scope only when the user invokes a write feature and has a verifiable entitlement. 7. Add negative tests confirming that arbitrary formatted keys and manually modified license files do not unlock Pro operations. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
docs/GOOGLE_CLOUD_SETUP.md:127
Finding
Credential Verification Commands May Print the Complete OAuth Client Secret<![CDATA[ ## Vulnerability Details **File Location**: `docs/GOOGLE_CLOUD_SETUP.md:127-152` **Vulnerability Type**: Sensitive credential exposure through terminal output **Risk Level**: Medium ### Vulnerable Code ```powershell # Create config directory 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 ``` ```bash # Create config directory mkdir -p ~/.config/gcal-pro # Move the downloaded file mv ~/Downloads/client_secret*.json ~/.config/gcal-pro/client_secret.json # Verify head -3 ~/.config/gcal-pro/client_secret.json ``` ### Technical Analysis The documentation instructs users to verify the credential file by printing its first three lines. OAuth client credential JSON is frequently serialized onto a single line. In that common case, `head -3` or `Get-Content ... | Select-Object -First 3` prints the entire document, including the client ID and client secret. Terminal output may be retained in Agent transcripts, CI logs, shell recordings, screen-sharing sessions, support captures, or other logging systems. The setup commands also do not explicitly establish restrictive permissions on the configuration directory or `client_secret.json`. Although a desktop OAuth client secret is not sufficient by itself to access the user’s calendar, it remains sensitive application credential material and should not be unnecessarily displayed or retained in logs. ### Attack Path 1. A user downloads a one-line Google OAuth client credential JSON document. 2. The user follows the documented verification command. 3. The shell prints the complete JSON document, including the OAuth client secret. 4. The output is retained by terminal logging, an AI Agent transcript, screen capt ...[truncated 764 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace content-printing verification with existence and metadata checks: ```bash test -f ~/.config/gcal-pro/client_secret.json && echo "Credential file found" ``` ```powershell if (Test-Path "$env:USERPROFILE\.config\gcal-pro\client_secret.json") { Write-Output "Credential file found" } ``` 2. Set restrictive permissions on Unix-like systems: ```bash mkdir -p -m 700 ~/.config/gcal-pro chmod 600 ~/.config/gcal-pro/client_secret.json ``` 3. On Windows, document an ACL configuration that grants access only to the current user. 4. If JSON validation is required, parse it and report only whether required field names exist. Never print their values. 5. Add a warning that OAuth credential contents must not be pasted into chat, support tickets, logs, screenshots, or Agent prompts. 6. Document credential rotation procedures in case the client secret has already been exposed. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unbounded and Unhashed Dependency Installation Is Not Reproducible<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-7` **Vulnerability Type**: Unlocked third-party dependency supply chain **Risk Level**: Low ### Vulnerable Code ```text # gcal-pro dependencies 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 executes these unconstrained requirements directly: ```text pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses a lower bound without an upper bound, exact version, or integrity hash. Two installations at different times may consequently resolve to different package versions. Future releases are accepted automatically even if they introduce incompatible behavior or are compromised upstream. The reviewed package names are consistent with the declared Google Calendar functionality, and no typosquatted or clearly malicious dependency was identified. The risk arises from non-reproducible resolution and absence of artifact integrity verification rather than from evidence that the currently named packages are malicious. Because Python packages can execute code during installation and are imported into a process handling OAuth tokens and calendar data, compromise of a resolved dependency could have significant consequences. ### Attack Path 1. A future release of an allowed dependency or transitive dependency is compromised, malicious, or unexpectedly incompatible. 2. A user runs `pip install -r requirements.txt`. 3. The resolver selects the new release because it satisfies the unbounded `>=` constraint. 4. Package installation or later import executes the affected code. 5. Code runs with the installing user’s privileges and may access files or credentials available to that process, including the Skill’s OAuth configuration. ### Impact Assessment A compromised dependency could execute with the local user’s privileges and potentially read ...[truncated 381 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate a reviewed lock file with exact versions for direct and transitive dependencies. 2. Use hash verification, for example through `pip-compile --generate-hashes`, and install with: ```bash pip install --require-hashes -r requirements-lock.txt ``` 3. Retain a human-maintained input file for desired version ranges and a generated lock file for production installation. 4. Introduce automated dependency vulnerability and provenance scanning. 5. Update dependencies through a controlled process that includes changelog review, tests, and deliberate regeneration of hashes. 6. Prefer installation inside a dedicated virtual environment rather than the user’s global Python environment. ]]>
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 (58)

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
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented purpose is calendar management, but the detected behavior includes license activation/deactivation, machine fingerprinting, and local license-state handling that are not clearly disclosed in the main description. This mismatch can hide sensitive side effects from users and reviewers, weakening informed consent and making it harder to assess what local data the skill manipulates.

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
87% confidence
Finding
The file locations section explicitly documents storage of OAuth client credentials, access tokens, and license data in a predictable path under the user's home directory. In a skill that also appears to use file and shell capabilities, predictable local secret storage increases the risk of unauthorized access, leakage, or misuse by other components or compromised prompts.

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
89% confidence
Finding
The documented presence of an auto-generated access token on disk means long-lived authentication material may be locally persisted in a predictable location. If the agent environment, shell access, or another tool can read that file, an attacker could gain calendar access and act as the user against Google APIs.

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
# 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
⚠️ **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.

Credential Access

High
Category
Privilege Escalation
Content
Add to `.gitignore`:
```
client_secret.json
token.json
*.json
```
Confidence
89% confidence
Finding
The suggested `.gitignore` entry `*.json` is overly broad and can cause developers to ignore all JSON files in the repository, potentially hiding security-relevant configuration, policy, or manifest changes from version control and code review. While not direct credential theft, this weakens auditability and can lead to accidental omission of important non-secret files.

Static analysis

No suspicious patterns detected.