T09 · Insecure Skill Coding Practices
- Location
SKILL.md:39- Finding
Shell Command Injection Through Unsanitized Skill Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Gmail summary skill is purpose-aligned, but it needs review because it handles private email and OAuth tokens with weak scoping and unsafe argument/content boundaries.
Install only if you are comfortable granting read-only Gmail access and having email text processed by the agent for summarization. Use a private credentials directory, review or restrict token.json permissions, avoid passing free-form arguments, and do not let the agent follow instructions contained inside emails without separate confirmation.
SKILL.md:39Shell Command Injection Through Unsanitized Skill Arguments
SKILL.md:43Indirect Prompt Injection Through Untrusted Email Content
scripts/fetch_emails.py:40OAuth Refresh Token Stored Without Enforced Restrictive Permissions
requirements.txt:1Non-Reproducible Third-Party Dependency Resolution
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Click "Create Credentials" > "OAuth client ID"
- Choose "Desktop app" as application type
- Download the credentials JSON file
5. Save the credentials file to a secure location (e.g., `~/.config/gmail/credentials.json`)
### 3. Set Environment Variable
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Click "Create Credentials" > "OAuth client ID"
- Choose "Desktop app" as application type
- Download the credentials JSON file
5. Save the credentials file to a secure location (e.g., `~/.config/gmail/credentials.json`)
### 3. Set Environment Variable
The declared purpose emphasizes concise email summaries, but the described behavior implies reading full unread email contents and possibly returning raw or truncated bodies while using Gmail OAuth credentials. That mismatch is dangerous because it can cause over-collection and over-exposure of highly sensitive private communications beyond what the user reasonably expects from the description.
The skill does not clearly warn users that it accesses private Gmail messages and may send email content through an AI summarization flow. In this context, the missing disclosure is especially dangerous because email bodies often contain credentials, financial information, personal data, and legal or business-sensitive content that users may not expect to be processed or transmitted.
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.
### 2. Set Up Gmail API Credentials
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project (or select an existing one)
3. Enable the Gmail API:
- Navigate to "APIs & Services" > "Library"
- Search for "Gmail API"
The skill requests access to sensitive resources and behaviors—environment variables, network access, and implied file writes for credential/token handling—without declaring an explicit tool scope or permissions boundary. This creates a transparency and least-privilege failure: an agent or user may invoke the skill without understanding it can access Gmail credentials, contact Gmail over the network, and potentially persist OAuth tokens.
The invocation text is broad enough to match many ordinary email-related requests, increasing the chance the skill is auto-invoked in situations where the user did not specifically consent to Gmail access. In the context of a skill that reads private inbox contents, overbroad triggering raises the risk of unintended data access and unnecessary transmission of sensitive email content for summarization.
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(token_path, 'w') as token:
token.write(creds.to_json())
return creds, None
The skill advertises concise summaries but actually returns raw message bodies and snippets, causing substantially more mailbox content to be exposed to the agent or downstream consumers than users would reasonably expect. In an email-reading skill, this mismatch increases privacy risk because sensitive content may be transmitted, logged, or processed unnecessarily.
The script prints fetched email subjects, senders, snippets, and body content directly as JSON, which can expose sensitive mailbox data to logs, calling processes, or other components without any explicit disclosure boundary. In the context of an agent skill, this is more dangerous because the output is designed for machine consumption and may be retained, forwarded, or incorporated into broader workflows automatically.
The dependency is specified with a lower bound only, allowing future unreviewed versions to be installed. This weakens build reproducibility and can introduce vulnerable or breaking upstream releases into a skill that handles sensitive Gmail access tokens and email data.
google-auth>=2.25.0
google-auth-oauthlib>=1.2.0
google-auth-httplib2>=0.2.0
google-api-python-client>=2.110.0
Using an unpinned version for google-auth-oauthlib permits installation of any newer release that satisfies the minimum version, including potentially vulnerable or maliciously compromised versions. Because this skill performs OAuth flows for Gmail access, supply-chain instability is somewhat more sensitive than in a non-privileged utility.
google-auth>=2.25.0
google-auth-oauthlib>=1.2.0
google-auth-httplib2>=0.2.0
google-api-python-client>=2.110.0
The package is not pinned to an exact version, so deployments may resolve to different dependency versions over time. In a skill integrating with Gmail APIs, this increases supply-chain risk and can affect authentication or HTTP transport behavior unexpectedly.
google-auth>=2.25.0
google-auth-oauthlib>=1.2.0
google-auth-httplib2>=0.2.0
google-api-python-client>=2.110.0
A minimum-only version constraint for google-api-python-client allows unreviewed newer versions into production, reducing reproducibility and increasing exposure to upstream security or compatibility issues. Since this library is used to access Gmail data, dependency integrity matters more than for low-privilege components.
google-auth>=2.25.0
google-auth-oauthlib>=1.2.0
google-auth-httplib2>=0.2.0
google-api-python-client>=2.110.0
The manifest says the skill fetches recent emails from Gmail, but the inline comment and query explicitly target unread messages only. This is an intent-level contradiction because 'recent' and 'unread' are different selection criteria and could materially change behavior.
No suspicious patterns detected.