Back to skill

Security audit

google-sheets-connect

Security checks for vulnerabilities and agentic risk

Overview

Review is recommended because the login flow exposes sensitive authorization codes and the formatting command can bypass deletion safeguards.

Before connecting an important account, request a protected login callback that keeps authorization codes out of chat, formatting restricted to formatting operations, and narrower file access where possible. The delete command permanently removes files rather than moving them to trash, as documented by [Google](https://developers.google.com/workspace/drive/api/reference/rest/v3/files/delete). Disconnect through Google account permissions when finished; local logout alone does not revoke access.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/gdrive_connect.py
Finding

Unclaimed loopback callback without PKCE permits OAuth code theft

Content
View full analysis

Impact

The attacker can redeem the intercepted code before the owner, obtaining access and potentially an offline refresh token for the requested full Drive and Sheets scopes. This permits unauthorized reading, modification, and deletion of accessible Google files.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (15)

Tainted flow: 'req' from os.environ.get (line 91, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The exchange destination can be replaced through GD_EXCHANGE_ENDPOINT without validating its scheme or host, and the request includes the authorization code and client credentials. If an attacker can influence this configuration, sensitive material can be sent to an attacker-controlled endpoint or over plaintext HTTP; ordinary exchange with Google's default endpoint is legitimate.

Content

Scanner excerpt · scripts/gdrive_connect.py (reported line 95)May include surrounding context.

python
url, data=body, headers={"Content-Type": "application/x-www-form-urlencoded"}
    )
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            return json.loads(r.read().decode() or "{}"), None
    except urllib.error.HTTPError as e:
        raw = e.read().decode(errors="replace")

Tainted flow: 'req' from os.environ.get (line 108, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/gdrive_connect.py (reported line 110)May include surrounding context.

python
def get_json(url, session_value, timeout=30):
    req = urllib.request.Request(url, headers={"Authorization": "Bearer " + session_value})
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            return json.loads(r.read().decode() or "{}"), None
    except urllib.error.HTTPError as e:
        raw = e.read().decode(errors="replace")

Tainted flow: 'req' from os.environ.get (line 83, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/gdrive_ops.py (reported line 88)May include surrounding context.

python
headers={"Content-Type": "application/x-www-form-urlencoded"},
    )
    try:
        with urllib.request.urlopen(req, timeout=30) as r:
            res = json.loads(r.read().decode())
    except urllib.error.HTTPError as e:
        out(f"❌ Làm mới phiên thất bại (HTTP {e.code}): {e.read().decode(errors='replace')[:300]}")

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The authorization and local session-storage behavior matches part of the description, but the supplied code does not implement the advertised end-to-end Sheets test. Its successful authorization path only calls Drive's about endpoint. The claim that Cloud Console is unnecessary is also conditional on obtaining suitable OAuth app credentials elsewhere, a prerequisite the description does not disclose. No unrelated malicious activity is evident in this chunk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

File discovery, reading, editing, and explicit deletion are documented capabilities, so those alone do not substantiate a hidden-purpose claim. However, the identified unrestricted batchUpdate implementation behind 'format' permits destructive operations that bypass the skill's stated deletion-confirmation boundary.

Content

No source excerpt is available for this finding.

The format command can delete tabs without the documented deletion authorization.

High
Category
Excessive Agency
Confidence
100% confidence
Finding

The format command forwards arbitrary Sheets batchUpdate requests without checking their operation types or invoking the deletion guard. A deleteSheet request can therefore remove a tab without --yes, and other requests can overwrite data while being presented as formatting.

Content

No source excerpt is available for this finding.

The skill exposes permanent deletion of arbitrary accessible Drive files beyond the advertised connection and Sheet test workflow.

High
Category
Excessive Agency
Confidence
94% confidence
Finding

The manifest describes connecting an OAuth session and testing creation, writing, and formatting of a Sheet. L300-L304 instead provide a general Drive DELETE operation on a caller-supplied file ID, with no restriction to spreadsheets or resources created by the test; this can permanently delete unrelated accessible Drive files, subject to the session's actual permissions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SETUP-ADMIN.md (reported line 97)May include surrounding context.

Cách B — bằng tay (nếu không dùng agent):

bash
mkdir -p ~/.config/gdrive-connect && chmod 700 ~/.config/gdrive-connect
printf '{"client_id":"%s","client_sec":"%s"}' "$CLIENT_ID" "$CLIENT_SECRET" > ~/.config/gdrive-connect/app.json
chmod 600 ~/.config/gdrive-connect/app.json

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 123)May include surrounding context.

  1. APIs & Services → Credentials → Create credentials → OAuth client ID → Desktop app → copy về 2 mã: Client ID và mã app thứ hai (ô Client se… trên màn hình).
  2. Lưu 2 mã đó vào tệp ngoài repo, quyền 600:
bash
mkdir -p ~/.config/gdrive-connect && chmod 700 ~/.config/gdrive-connect
printf '{"client_id":"%s","client_sec":"%s"}' "$CLIENT_ID" "$CLIENT_SECRET" > ~/.config/gdrive-connect/app.json
chmod 600 ~/.config/gdrive-connect/app.json

The setup instructs users to paste a Google OAuth authorization code into agent chat without warning about exposing account-access material to the chat service.

Medium
Category
Output Handling
Confidence
98% confidence
Finding

The instructions place a live OAuth authorization code in chat, exposing it to chat retention, logging, and anyone able to access the conversation. Before redemption or expiry, an intercepted code may be exchanged for account-access tokens; the desktop application's shared client secret is not an effective confidentiality boundary.

Content

No source excerpt is available for this finding.

Skill declares no tool scope ('permissions' or 'allowed-tools') but code capabilities were detected: env, file_write, network, shell.

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Requests unrestricted Drive authorization rather than permissions limited to the stated Sheets workflow.

Medium
Category
Excessive Agency
Confidence
92% confidence
Finding

The connector requests full Drive access rather than limiting access to files created or explicitly selected for the application. Although broader Drive operations are documented, making this the default substantially increases the consequences of token theft, agent misuse, or prompt injection beyond the basic connection and spreadsheet-creation workflow.

Content

No source excerpt is available for this finding.

Convenience instructions ask users to disclose OAuth credentials in chat.

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

The program explicitly asks the user to paste a callback URL containing a live authorization code into chat. The flow uses no PKCE challenge, so someone obtaining that code and the distributed desktop client credentials could race its redemption and obtain tokens with broad Drive access.

Content

No source excerpt is available for this finding.

The connection flow does not perform the promised spreadsheet creation, writing, or formatting test.

Medium
Category
Excessive Agency
Confidence
99% confidence
Finding

The manifest promises that the agent saves the session and tests creating, writing, and formatting a real Sheet. After saving the session, L235-L254 only retrieve account identity and storage quota through Drive's about endpoint; the file implements no spreadsheet creation, value updates, or formatting requests, so successful connection does not verify the advertised write capabilities.

Content

No source excerpt is available for this finding.

Selftest unconditionally deletes its test resources despite the documented deletion opt-in requirement.

Medium
Category
Excessive Agency
Confidence
100% confidence
Finding

The safety rule at L021 states that deletion runs only with --yes or GDRIVE_ALLOW_DELETE=1. These DELETE calls execute without checking either condition, and the selftest parser at L441-L442 does not offer --yes; although limited to newly created test resources, this directly contradicts the stated guarantee.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.