Back to skill

Security audit

Gmail Auto Draft

Security checks for vulnerabilities and agentic risk

Overview

This Gmail automation is not clearly malicious, but it should be reviewed carefully because it can read and modify Gmail data and may expose email contents or a local gateway token to a configured model endpoint.

Install only if you are comfortable granting Gmail modify/compose access and having selected email contents sent to the configured model service. Prefer the local loopback endpoint or an explicitly trusted HTTPS provider, set a dedicated OPENAI_API_KEY for external providers, avoid relying on the OpenClaw gateway token fallback, narrow Gmail queries, test without --mark-read, and protect or rotate OAuth/token files if they may have been exposed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/gmail_auto_draft.py:40
Finding

Gateway Credential and Email Disclosure Through an Unrestricted Model Endpoint

Content
View full analysis
str: cfg_path = Path("~/.openclaw/openclaw.json").expanduser() if not cfg_path.exists(): return "" try: cfg = json.loads(cfg_path.read_text(encoding="utf-8")) except Exception: return "" return cfg.get("gateway", {}).get("auth", {}).get("token", "") ``` ```python user = ( f"Agency profile:\n{agency_profile}\n\n" f"Style rules:\n{style_rules}\n\n" f"Incoming email metadata:\n" f"From Name: {record.from_name or 'Unknown'}\n" f"From Email: {record.from_email or 'Unknown'}\n" f"Subject: {record.subject or '(no subject)'}\n\n" f"Incoming email content:\n{record.body[:12000]}\n\n" "Write a personalized follow-up reply as if replying in the same thread. " "Include a clear next step and keep it under 180 words unless complexity requires more." ) ``` ```python resp = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": system}, {"role": "user", "content": user}, ], temperature=0.4, ) ``` ```python parser.add_argument("--openai-model", default=os.environ.get("OPENAI_MODEL", "openclaw:main")) parser.add_argument("--openai-base-url", default=os.environ.get("OPENAI_BASE_URL", "http://127.0.0.1:18789/v1")) ``` ```python openai_api_key = os.environ.get("OPENAI_API_KEY", "") or load_gateway_token() ``` ```python openai_client = OpenAI(api_key=openai_api_key, base_url=args.openai_base_url) ``` ### Technical Analysis The OpenAI-compatible base URL can be supplied through the `--openai-base-url` argument or the `OPENAI_BASE_URL` environment variable without host validation, transport validation, or an endpoint allowlist. If ...[truncated 1981 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/gmail_auto_draft.py:120
Finding

Indirect Prompt Injection Through Untrusted Email Content

Content
View full analysis
tuple[str, str]: system = ( "You are an assistant that writes short, personalized sales follow-up emails for a digital marketing agency. " "Be professional, warm, and specific. Do not invent facts. " "If details are missing, ask one concise clarifying question in the draft. " "Return plain text only." ) user = ( f"Agency profile:\n{agency_profile}\n\n" f"Style rules:\n{style_rules}\n\n" f"Incoming email metadata:\n" f"From Name: {record.from_name or 'Unknown'}\n" f"From Email: {record.from_email or 'Unknown'}\n" f"Subject: {record.subject or '(no subject)'}\n\n" f"Incoming email content:\n{record.body[:12000]}\n\n" "Write a personalized follow-up reply as if replying in the same thread. " "Include a clear next step and keep it under 180 words unless complexity requires more." ) return system, user ``` ```python def generate_reply_text(client: OpenAI, model: str, record: EmailRecord, agency_profile: str, style_rules: str) -> str: system, user = build_reply_prompt(record, agency_profile, style_rules) resp = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": system}, {"role": "user", "content": user}, ], temperature=0.4, ) text = resp.choices[0].message.content or "" return text.strip() ``` ```python reply_text = generate_reply_text( client=openai_client, model=args.openai_model, record=record, agency_profile=args.agency_profile, style_rules=args.style_rules, ) draft_id = create_gmai ...[truncated 2334 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/gmail_auto_draft.py:180
Finding

Gmail OAuth Refresh Token Stored Without Explicit Restrictive Permissions

Content
View full analysis
Remediation
View remediation
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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (19)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/setup.md (reported line 5)May include surrounding context.

md
## 0) 接入方必须先提供

- Gmail OAuth 客户端文件:`~/.config/gmail-auto-draft/google-client-secret.json`
- 目标 Gmail 账号(如应用在 Testing,需加入测试用户)
- 固定关键词查询(`--query` 或 `--query-file`)
- 业务画像(`agency_profile.txt`)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/setup.md (reported line 25)May include surrounding context.

md
## 0) 接入方必须先提供

- Gmail OAuth 客户端文件:`~/.config/gmail-auto-draft/google-client-secret.json`
- 目标 Gmail 账号(如应用在 Testing,需加入测试用户)
- 固定关键词查询(`--query` 或 `--query-file`)
- 业务画像(`agency_profile.txt`)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/gmail_auto_draft.py (reported line 322)May include surrounding context.

python
## 0) 接入方必须先提供

- Gmail OAuth 客户端文件:`~/.config/gmail-auto-draft/google-client-secret.json`
- 目标 Gmail 账号(如应用在 Testing,需加入测试用户)
- 固定关键词查询(`--query` 或 `--query-file`)
- 业务画像(`agency_profile.txt`)

Ssd 1

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Untrusted email content is inserted directly into the LLM prompt as authoritative context, so an attacker can embed instructions in an email that manipulate the generated reply. In this skill's context, prompt injection is especially dangerous because the output is turned into a Gmail draft in the victim's mailbox, enabling social-engineering amplification, policy bypass, or misleading client communications.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script sends incoming email bodies, sender metadata, and subject lines to an external LLM endpoint for draft generation without any runtime consent gate, redaction, or trust check. Because emails frequently contain confidential client data, this can leak sensitive communications to third-party or locally proxied model services.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises functionality that reads Gmail, uses environment-based credentials, accesses local files, and makes network calls, but the manifest does not declare any tool scope or permissions. This creates a mismatch between documented behavior and declared capability boundaries, which can lead to over-privileged execution, insufficient review, and accidental exposure of email contents or secrets to external services.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file applies to SQP-2, and it instructs users to enable --mark-read, which affects user data by altering email read/unread state. While early testing guidance exists, the production instruction does not explicitly warn that the action mutates mailbox state and may hide messages from normal unread workflows.

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 · references/setup.md (reported line 18)May include surrounding context.

md
---

## 1) Create Google OAuth credentials

1. Open Google Cloud Console.
2. Create/select a project.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation tells users to configure OAuth tokens and API keys and states where token files are stored, but it does not explicitly instruct users to protect those credentials as sensitive secrets. In a Gmail automation skill, exposed OAuth tokens or API keys could allow unauthorized access to mailbox data, draft creation, or abuse of the connected model backend.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The setup instructs users to run a continuous Gmail polling and drafting workflow, but it does not clearly warn that this changes mailbox state by creating drafts repeatedly and potentially acting on live customer communications. In this skill context, the risk is elevated because the automation monitors a real inbox and generates personalized replies, so misuse, bad prompts, or incorrect queries could cause unintended mailbox modifications at scale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documented continuous demo command includes --mark-read, which changes mailbox state by marking messages as read, but the surrounding instructions do not clearly warn the operator that this is a destructive state-changing action. In a Gmail monitoring skill, this can cause users to miss unread emails or alter workflow/audit expectations, especially in shared or business inboxes where unread status is operationally significant.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Gmail search query is broad enough to match many ordinary inbound emails based on common sales and help-seeking phrases such as "looking for," "need help," and "can you help." In this skill, matching an email triggers automated reading and AI-generated reply drafting, so overbroad selection can cause unintended processing of unrelated or sensitive emails and create inappropriate draft responses for human review.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script falls back to reading a token from ~/.openclaw/openclaw.json and reuses it as the OpenAI API key, even though that token belongs to a different local gateway trust boundary. This broadens credential exposure and creates confused-deputy behavior: anyone running the skill may unknowingly authorize outbound email-content transfer with an unrelated credential.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

After generating a draft, the script modifies message state by adding a processed label and optionally removing UNREAD, which changes the user's mailbox without an explicit confirmation step at execution time. In an automation context, this can hide messages from normal triage workflows or create missed-response risk if the AI-produced draft is poor or processing is triggered unexpectedly.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest describes Gmail inbox monitoring and AI-assisted draft creation, but the code also accepts arbitrary filesystem paths and reads their contents into runtime behavior. Local file ingestion is not mentioned in the skill description and is not an obvious requirement for basic Gmail auto-drafting.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with only a lower bound, so future installs may resolve to any newer release, including versions with breaking changes or compromised upstream packages. In a skill that processes Gmail data and uses OpenAI, a supply-chain issue in a dependency could affect sensitive email content or OAuth handling, even though this file alone does not prove exploitation.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
google-api-python-client>=2.170.0
google-auth>=2.35.0
google-auth-oauthlib>=1.2.1
openai>=1.75.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Using an unpinned google-auth version allows installation of unexpected future releases, increasing exposure to supply-chain compromise or unreviewed behavioral changes in authentication code. Because this skill relies on Google auth for mailbox access, dependency drift in this area is somewhat more sensitive than in a non-privileged utility.

Content

Scanner excerpt · scripts/requirements.txt (reported line 2)May include surrounding context.

text
google-api-python-client>=2.170.0
google-auth>=2.35.0
google-auth-oauthlib>=1.2.1
openai>=1.75.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The oauthlib-related dependency is unpinned, which weakens build reproducibility and permits unreviewed newer versions to enter the environment. Since OAuth libraries participate in token acquisition and refresh flows, a malicious or flawed release could affect account access or token security for Gmail integration.

Content

Scanner excerpt · scripts/requirements.txt (reported line 3)May include surrounding context.

text
google-api-python-client>=2.170.0
google-auth>=2.35.0
google-auth-oauthlib>=1.2.1
openai>=1.75.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The OpenAI SDK is also unpinned, allowing future package versions to be pulled without review. In this skill's context, that could alter request handling or introduce supply-chain risk affecting potentially sensitive email-derived prompts and drafts, though the issue remains a low-severity hygiene weakness rather than direct malicious logic.

Content

Scanner excerpt · scripts/requirements.txt (reported line 4)May include surrounding context.

text
google-api-python-client>=2.170.0
google-auth>=2.35.0
google-auth-oauthlib>=1.2.1
openai>=1.75.0

Static analysis

No suspicious patterns detected.