Back to skill

Security audit

meeting-prep

Security checks for vulnerabilities and agentic risk

Overview

The skill has a legitimate meeting-prep purpose, but it asks for broad calendar and GitHub credentials and can run scheduled team-wide summaries without enough scoping.

Review carefully before installing. Use read-only Calendar access, a fine-grained GitHub token or GitHub App limited to the exact repositories needed, secure secret storage instead of project-local plaintext files, and explicit controls for which calendars, repos, developers, recipients, and schedules are allowed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:17
Finding
Overprivileged Google Calendar OAuth Scope## Vulnerability Details **File Location**: `SKILL.md`, lines 17-25 **Vulnerability Type**: Excessive OAuth permissions **Risk Level**: Medium ### Vulnerable Code ```markdown ### Google Calendar OAuth Create OAuth credentials in Google Cloud Console: 1. Enable Google Calendar API 2. Create OAuth 2.0 Desktop credentials 3. Store `client_secret.json` in `credentials/` 4. Authorize with scopes: `https://www.googleapis.com/auth/calendar` 5. Store tokens in `credentials/calendar_tokens.json` ``` ### Technical Analysis The Skill requests the full Google Calendar OAuth scope, `https://www.googleapis.com/auth/calendar`. This scope permits management operations beyond the read-only access required by the declared workflow, which only queries upcoming events and checks for video-conference links. Requesting full Calendar access violates the principle of least privilege. Although the documented API request is read-only and sends credentials only to an official Google endpoint, the resulting bearer token may authorize calendar modification operations if the Agent, local environment, or token file is compromised. The instructions also place OAuth tokens in a predictable local plaintext file. No unrelated recipient or deliberate credential exfiltration was identified, but exposure of this file would make the excessive scope exploitable. ### Attack Path 1. A local attacker, malicious process, or compromised Agent obtains access to `credentials/calendar_tokens.json`. 2. The attacker extracts the access token or refresh token. 3. If necessary, the refresh token and OAuth client credentials are submitted to Google's official token endpoint to obtain a new access token. 4. The attacker uses the resulting broadly scoped bearer token with Google Calendar API endpoints. 5. The attacker performs operations beyond meeting retrieval, potentially including creating, modifying, or deleting calendar data within the permissions granted ...[truncated 482 chars]
Remediation
## Remediation Suggestions 1. Replace the full Calendar scope with the read-only scope: ```text https://www.googleapis.com/auth/calendar.readonly ``` 2. Revoke existing grants and reauthorize the application so previously issued broadly scoped refresh tokens cannot continue to be used. 3. Use an OAuth client dedicated to this Skill and restrict access to only the required Google account. 4. Store token files outside the project directory in an operating-system credential store or secrets manager. 5. If local files are unavoidable, enforce owner-only permissions, such as mode `0600`, and exclude the entire credentials directory from version control and backups not designed for secrets. 6. Document token rotation, revocation, and incident-response procedures. 7. Validate that all Calendar operations remain read-only and restrict requests to the minimum fields required for meeting preparation.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:29
Finding
Overprivileged Classic GitHub Personal Access Token## Vulnerability Details **File Location**: `SKILL.md`, lines 29-31 **Vulnerability Type**: Excessive repository permissions **Risk Level**: High ### Vulnerable Code ```markdown ### GitHub Token Create a classic Personal Access Token with `repo` scope. Store at `credentials/github_token`. ``` ### Technical Analysis The Skill instructs users to create a classic GitHub personal access token with the broad `repo` scope. The declared functionality only needs to enumerate configured repositories and read commit metadata. A classic token with `repo` scope can grant substantially broader access to private repositories, including write-capable operations, depending on the authenticated user's repository privileges. This violates least privilege and unnecessarily increases the consequences of token leakage or Agent compromise. The predictable plaintext location, `credentials/github_token`, further increases exposure if filesystem access controls are weak, the project directory is archived, or the credential is accidentally committed. The documented network calls send the token only to the official `api.github.com` endpoint, so the audit found no direct transmission to an attacker-controlled host. The vulnerability is the breadth and storage of the credential rather than the legitimate authenticated API request itself. ### Attack Path 1. An attacker gains read access to the project directory, Agent workspace, backup, logs, or `credentials/github_token`. 2. The attacker extracts the classic personal access token. 3. The attacker authenticates to `api.github.com` or GitHub using the token. 4. The attacker enumerates repositories available to the token owner, including private repositories covered by `repo`. 5. The attacker reads sensitive source code and repository data or performs write operations allowed by the token and the owner's repository privileges. 6. The attacker may alter repository content or settings, enabling sour ...[truncated 707 chars]
Remediation
## Remediation Suggestions 1. Replace the classic PAT with a fine-grained personal access token or GitHub App credential. 2. Restrict the credential to the exact repositories configured for summary generation. 3. Grant only read-only `Contents` and `Metadata` permissions required to list repositories and retrieve commits. 4. Avoid granting repository write, administration, workflow, package, deployment, or organization-management permissions. 5. Store the credential in an operating-system keychain, secrets manager, or protected runtime secret rather than a plaintext project file. 6. If file storage is unavoidable, use owner-only permissions such as mode `0600`, prevent symlink traversal, and exclude the credentials directory from version control and ordinary backups. 7. Revoke the existing classic token after migration and establish short expiration periods and regular rotation. 8. Add repository allowlist validation before API requests so runtime configuration cannot silently expand access beyond the intended repositories. 9. Monitor GitHub token activity and configure alerts for unexpected repositories, write operations, or source locations.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (12)

Credential Access

High
Category
Privilege Escalation
Content
1. Enable Google Calendar API
2. Create OAuth 2.0 Desktop credentials
3. Store `client_secret.json` in `credentials/`
4. Authorize with scopes: `https://www.googleapis.com/auth/calendar`
5. Store tokens in `credentials/calendar_tokens.json`
Confidence
92% confidence
Finding
The instructions direct users to store OAuth client secrets and access tokens in local files under a predictable credentials directory. In a shared environment or poorly secured workstation, these files are high-value targets that can enable unauthorized calendar access and persistent account compromise via refresh tokens.

Credential Access

High
Category
Privilege Escalation
Content
### GitHub Token

Create a classic Personal Access Token with `repo` scope. Store at `credentials/github_token`.

## Workflows
Confidence
95% confidence
Finding
The skill recommends a classic GitHub Personal Access Token with broad 'repo' scope stored in a local file. Classic PATs often grant extensive repository access, and plaintext local storage makes theft or misuse significantly easier, potentially exposing private source code and commit history across the organization.

Credential Access

High
Category
Privilege Escalation
Content
Refresh Token

CLIENT_ID=$(jq -r '.installed.client_id' credentials/client_secret.json)
CLIENT_SECRET=$(jq -r '.installed.client_secret' credentials/client_secret.json)
REFRESH_TOKEN=$(jq -r '.refresh_token' credentials/calendar_tokens.json)
Confidence
93% confidence
Finding
The example explicitly reads client ID, client secret, and refresh token from local files for use in a shell command. This pattern normalizes direct credential handling in scripts, increasing exposure through filesystem theft, shell history, debugging output, and process inspection.

Credential Access

High
Category
Privilege Escalation
Content
Refresh Token

CLIENT_ID=$(jq -r '.installed.client_id' credentials/client_secret.json)
CLIENT_SECRET=$(jq -r '.installed.client_secret' credentials/client_secret.json)
REFRESH_TOKEN=$(jq -r '.refresh_token' credentials/calendar_tokens.json)

curl -s -X POST https://oauth2.googleapis.com/token \
Confidence
93% confidence
Finding
Reading the client secret from a local JSON file in plaintext is a credential-access risk because compromise of that file enables abuse of the OAuth client configuration and token refresh flow. In context, the skill also stores refresh tokens nearby, making the combined impact more serious.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill description does not warn users that it accesses Google Calendar contents and repository activity across multiple developers. This weakens informed consent and can cause users to enable a skill that processes sensitive scheduling and engineering activity data without understanding the scope.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill instructs users to store OAuth client secrets and tokens on disk but does not warn about the security implications of local credential storage or persistent state. If file permissions are weak or the host is shared, these credentials can be stolen and reused to access calendar or repository data.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger 'Cron every 15 minutes or heartbeat' is broad and can cause the skill to run without a clear user-initiated action. Because the skill accesses calendar data, GitHub activity, and may send notifications, over-broad activation increases the chance of unintended data access or message generation.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The daily summary trigger is underspecified as simply running at end of day, with no timezone, scope, approval, or recipient constraints. In a skill that aggregates commits across all developers, this can lead to unintended collection and distribution of team-wide activity data.

External Transmission

Medium
Category
Data Exfiltration
Content
CLIENT_SECRET=$(jq -r '.installed.client_secret' credentials/client_secret.json)
REFRESH_TOKEN=$(jq -r '.refresh_token' credentials/calendar_tokens.json)

curl -s -X POST https://oauth2.googleapis.com/token \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET" \
  -d "refresh_token=$REFRESH_TOKEN" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# List org repos
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.github.com/orgs/ORG_NAME/repos?per_page=50&sort=pushed"

# Get commits
curl -s -H "Authorization: Bearer $TOKEN" \
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# List org repos
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.github.com/orgs/ORG_NAME/repos?per_page=50&sort=pushed"

# Get commits
curl -s -H "Authorization: Bearer $TOKEN" \
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
79% confidence
Finding
The instruction "Plain text, no markdown, no emojis" imposes a fixed output format without indicating that the user can choose a different style or locale preference. This is a natural-language policy concern because it forces a communication format rather than offering user choice.

Static analysis

No suspicious patterns detected.