Back to skill

Security audit

Tmp

Security checks for vulnerabilities and agentic risk

Overview

The main CLI skill is understandable, but the package also includes separate Gmail gateway instructions and email-tracking code that expose sensitive mail data beyond the root disclosure.

Review before installing. Use this only if you trust the `gog` CLI and understand that bundled materials include broader Google account authority than the root description. Avoid the Maton nested Gmail gateway unless you explicitly intend to send Gmail traffic and a Maton API key through that service. Limit OAuth scopes, prefer read-only where possible, use the command allowlist for agent runs, and avoid email tracking unless you have a clear consent and privacy basis.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

other

Error
Location
gmail/SKILL.md:24
Finding
Gmail credentials and mailbox operations are routed through an unrelated third-party gateway<![CDATA[ ## Vulnerability Details **File Location**: `gmail/SKILL.md`, lines 24–38, 62–83, and 132–137 **Vulnerability Type**: Sensitive data disclosure through a third-party API proxy **Risk Level**: High ### Vulnerable Code ```python # Lines 24–28 import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/google-mail/gmail/v1/users/me/messages?maxResults=10') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) ``` ```text # Lines 33–38 https://gateway.maton.ai/google-mail/{native-api-path} ``` ```python # Lines 62–83 # Manage your Google OAuth connections at `https://ctrl.maton.ai`. # List connections req = urllib.request.Request( 'https://ctrl.maton.ai/connections?app=google-mail&status=ACTIVE' ) req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) # Create connection data = json.dumps({'app': 'google-mail'}).encode() req = urllib.request.Request( 'https://ctrl.maton.ai/connections', data=data, method='POST' ) req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) ``` ```python # Lines 132–137 req = urllib.request.Request( 'https://gateway.maton.ai/google-mail/gmail/v1/users/me/messages' ) req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '21fd90f9-5935-43cd-b6c8-bde9d915ca80') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) ``` ### Technical Analysis The nested Gmail Skill directs the agent to send the `MATON_API_KEY` and Gmail API requests to `gateway.maton.ai`. Connection creation, listing, selection, and deletion are similarly delegated to `ctrl.maton.ai`. This creates an additional trust boundary that is absent ...[truncated 2518 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the unrelated nested Gmail Skill from the root `gog` package unless third-party managed OAuth is an explicit part of the published product. 2. Prefer direct requests to official Google API endpoints using narrowly scoped OAuth tokens stored in the local operating-system keychain. 3. If Maton integration remains available: - Package it as a distinct Skill with separate metadata and ownership. - Require explicit informed user consent before transmitting credentials or mailbox content. - Clearly disclose that Gmail traffic passes through Maton infrastructure. - Document data retention, logging, subprocessors, incident response, and credential revocation procedures. - Restrict OAuth scopes to the specific requested operation. - Avoid a single bearer key that provides access to every connected account. - Support short-lived, connection-specific credentials. 4. Never print the API key in troubleshooting instructions. Replace `echo $MATON_API_KEY` with a non-disclosing presence check. 5. Provide connection and API-key revocation instructions and make revocation immediately effective. 6. Add package-level tests or policy checks that reject undeclared third-party API domains in nested Skill instructions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
gmail/gogcli/internal/tracking/worker/src/index.ts:90
Finding
Unauthenticated tracking-query endpoint exposes recipient and email-open metadata<![CDATA[ ## Vulnerability Details **File Location**: `gmail/gogcli/internal/tracking/worker/src/index.ts`, lines 20–23 and 90–137; related collection occurs at lines 40–88 **Vulnerability Type**: Missing authorization for sensitive tracking records **Risk Level**: High ### Vulnerable Code The router exposes `/q/:blob` without an authentication check: ```typescript // Lines 20–23 // Query endpoint: GET /q/:blob if (path.startsWith('/q/')) { return await handleQuery(request, env, path); } ``` The complete query handler decrypts the URL-carried identifier and returns recipient and open metadata without verifying an admin key or user session: ```typescript // Lines 90–137 async function handleQuery(request: Request, env: Env, path: string): Promise<Response> { const blob = path.slice(3); // Remove '/q/' const key = await importKey(env.TRACKING_KEY); let payload: PixelPayload; try { payload = await decrypt(blob, key); } catch { return new Response('Invalid tracking ID', { status: 400 }); } const result = await env.DB.prepare(` SELECT opened_at, ip, city, region, country, timezone, is_bot, bot_type FROM opens WHERE tracking_id = ? ORDER BY opened_at ASC `).bind( blob ).all(); const opens = result.results.map((row: any) => ({ at: row.opened_at, is_bot: row.is_bot === 1, bot_type: row.bot_type, location: row.city ? { city: row.city, region: row.region, country: row.country, timezone: row.timezone, } : null, })); const humanOpens = opens.filter((o: any) => !o.is_bot); return Response.json({ tracking_id: blob, recipient: payload.r, sent_at: new Date(payload.t * 1000).toISOString(), opens, total_opens: opens.length, human_opens: humanOpens.length, first_human_open: humanOpens[0] || null, }); } ``` The tracking-pixel handler records sensitive request metadata: ```typescript // Lines 40–88 async function handlePixel(request: Re ...[truncated 4341 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authorization for `/q/:blob`, using the same administrative authentication model as `/opens` or a dedicated authenticated user session. 2. Do not treat possession of the pixel URL as authorization to read tracking results. 3. Separate public pixel identifiers from private query identifiers: - Use a random, opaque pixel ID. - Store recipient metadata only on the server. - Require an authenticated account to map the ID to tracking records. 4. Do not return recipient addresses from query responses unless strictly required and authorized. 5. Minimize collected telemetry: - Avoid storing full IP addresses and user-agent strings. - Truncate or hash network identifiers where possible. - Avoid city-level location collection unless explicitly required. 6. Establish and enforce short retention periods for tracking records. 7. Provide deletion and opt-out mechanisms. 8. Clearly disclose tracking to senders and recipients where applicable, and ensure use complies with privacy and communications laws. 9. Add automated authorization tests confirming that anonymous requests to every tracking-report endpoint receive `401` or `403`. 10. Apply rate limiting and audit logging to authenticated query endpoints. 11. Rotate tracking keys after any URL disclosure incident; key rotation should invalidate old query capabilities where operationally appropriate. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (822)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description says this skill is a Google Workspace CLI for multiple Google services. The supplied code does not implement any CLI behavior or any interaction with Google Workspace resources. Instead, it is a small browser-side script for a docs site that reads text from a DOM element and re-renders it incrementally as an animated typing effect. This is materially different from the declared primary purpose, so it should be flagged as a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description lists support for Gmail, Calendar, Drive, Contacts, Sheets, and Docs, but this code chunk is specifically for Google Apps Script operations via the Script API. It can read script project metadata and content, execute script functions, and create new Apps Script projects. Apps Script is not mentioned in the declared purpose, and executing/creating script projects is a materially distinct capability from the listed Workspace services. Therefore the description does not accurately represent this code chunk's behavior.

Credential Access

High
Category
Privilege Escalation
Content
Use `gog` for Gmail/Calendar/Drive/Contacts/Sheets/Docs. Requires OAuth setup.

Setup (once)
- `gog auth credentials /path/to/client_secret.json`
- `gog auth add you@gmail.com --services gmail,calendar,drive,contacts,sheets,docs`
- `gog auth list`
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
Use `gog` for Gmail/Calendar/Drive/Contacts/Sheets/Docs. Requires OAuth setup.

Setup (once)
- `gog auth credentials /path/to/client_secret.json`
- `gog auth add you@gmail.com --services gmail,calendar,drive,contacts,sheets,docs`
- `gog auth list`
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Hidden Instructions

High
Category
Prompt Injection
Content
# 🧭 gogcli — Google in your terminal.

![GitHub Repo Banner](https://ghrb.waren.build/banner?header=gogcli%F0%9F%A7%AD&subheader=Google+in+your+terminal&bg=f3f4f6&color=1f2937&support=true)
<!-- Created with GitHub Repo Banner by Waren Gonzaga: https://ghrb.waren.build -->

Fast, script-friendly CLI for Gmail, Calendar, Chat, Classroom, Drive, Docs, Slides, Sheets, Forms, Apps Script, Contacts, Tasks, People, Groups (Workspace), and Keep (Workspace-only). JSON-first output, multiple accounts, and least-privilege auth built in.
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Credential Access

High
Category
Privilege Escalation
Content
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
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
## How it works

- Default client name: `default`
- Default credentials file: `$(os.UserConfigDir())/gogcli/credentials.json`
- Named credentials files: `$(os.UserConfigDir())/gogcli/credentials-<client>.json`
- Tokens are stored per client (`token:<client>:<email>`). Default client also writes legacy keys for backwards compatibility.
- Default account is stored per client, with a legacy global fallback for the default client.
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

Detected: suspicious.exposed_resource_identifier, suspicious.exposed_secret_literal

Example code exposes a concrete connection_id instead of a placeholder.

Critical
Code
suspicious.exposed_resource_identifier
Location
gmail/SKILL.md:103

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
gmail/gogcli/internal/config/credentials.go:39

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
gmail/gogcli/internal/googleauth/accounts_server.go:253

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
gmail/gogcli/internal/googleauth/oauth_flow_manual.go:24

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
gmail/gogcli/internal/googleauth/oauth_flow.go:126

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
gmail/gogcli/internal/googleauth/token_check.go:24

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
gmail/gogcli/internal/googleauth/token_email.go:30