T09 · Insecure Skill Coding Practices
- Location
scripts/claim_free_mailbox.py:39- Finding
API Key Can Be Redirected to an Arbitrary Network Destination
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Mailgo cold-email skill is purpose-aligned, but it needs review because it can use account credentials, upload recipient data, activate/delete campaigns, and read reply bodies with several under-scoped safeguards.
Install only after reviewing the credential and sending safeguards. Use a dedicated/revocable Mailgo token through protected secret storage, do not paste it into chat, avoid --api-key and --base-url, use --dry-run or an explicit final confirmation before activation, and confirm legal basis/consent before uploading lead lists or reading reply bodies.
scripts/claim_free_mailbox.py:39API Key Can Be Redirected to an Arbitrary Network Destination
gpt/system-prompt.md:5System Prompt Instructs the Agent to Request an API Key in Conversation
scripts/claim_free_mailbox.py:94API Key Is Accepted Through Command-Line Arguments and Recommended for Plaintext Shell Startup Storage
scripts/run_campaign.py:189Optional Spreadsheet Dependency Is Installed Without Version or Integrity Pinning
scripts/campaign_control.py:61Campaign Deletion Lacks a Code-Level Confirmation Safeguard
If the skill can read reply email bodies via a mail proxy while advertising only broad 'reporting', users may authorize it without understanding that message content—not just aggregate metrics—will be accessed. That mismatch can lead to over-collection of sensitive business or personal communications.
If the skill can read reply email bodies via a mail proxy while advertising only broad 'reporting', users may authorize it without understanding that message content—not just aggregate metrics—will be accessed. That mismatch can lead to over-collection of sensitive business or personal communications.
If the skill can read reply email bodies via a mail proxy while advertising only broad 'reporting', users may authorize it without understanding that message content—not just aggregate metrics—will be accessed. That mismatch can lead to over-collection of sensitive business or personal communications.
If the skill can read reply email bodies via a mail proxy while advertising only broad 'reporting', users may authorize it without understanding that message content—not just aggregate metrics—will be accessed. That mismatch can lead to over-collection of sensitive business or personal communications.
If the skill can read reply email bodies via a mail proxy while advertising only broad 'reporting', users may authorize it without understanding that message content—not just aggregate metrics—will be accessed. That mismatch can lead to over-collection of sensitive business or personal communications.
The lead import operation uploads multiple pieces of personally identifiable and business contact information, including email, name, company, title, and domain, without any accompanying privacy warning or consent guidance. In a cold-email context, bulk transfer of lead data is especially sensitive because it can implicate privacy law, data brokerage concerns, and unauthorized processing of third-party contact lists.
This endpoint retrieves full email message content, which may contain sensitive replies, personal data, commercial information, or security-relevant details. Without an explicit warning or constrained scope, an agent could access private communications beyond what a user reasonably expects from campaign analytics or management features.
The skill declares access to sensitive capabilities in practice (environment secrets, file input, and network/API use) but does not constrain them with an explicit tool/permission scope. That increases the blast radius of prompt injection or accidental misuse because the agent may read local files, use the API key, and make external requests beyond what is minimally necessary.
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.
---
name: mailgo-campaign-suite
description: Complete cold email campaign suite for Mailgo — verify recipients, claim free mailbox, generate & optimize content, create campaigns, manage lifecycle, and view reports. All-in-one skill that handles the full outreach pipeline end-to-end. Use when a user wants to send cold emails, launch outreach campaigns, or manage existing campaigns.
env:
MAILGO_API_KEY:
required: true
The activation text is broad enough to trigger on ordinary requests about email or campaign management, increasing the chance the skill will activate in contexts where the user did not intend outbound cold-email automation. Overbroad activation can expose recipient data, stored context, and API-backed actions to unrelated conversations.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
| 11 | Do you have recipients' **job titles**? (column name or yes/no) | `has_title` |
| 12 | Do you have recipients' **company websites / domains**? (column name or yes/no) | `has_domain` |
> If the user provides a file, auto-detect columns after reading the file headers — then mark fields 9–12 automatically without asking again.
>
> **⚠ Header Warning:** Column detection relies entirely on header names. Files without headers (e.g. a bare two-column XLSX with email + company but no row of column names) will only have `col_0`, `col_1`, … as synthetic headers — none of which match any known field name. As a result, **only the email column can be identified by content scanning; all other columns (company, name, title, domain) will be silently discarded.**
> Whenever a user provides a headerless file and you can see that extra columns exist (e.g. "two-column spreadsheet"), **proactively warn them**:
Silently deriving names from email local-parts and storing them as recipient identity data creates inferred personal data without notice and may produce inaccurate or sensitive inferences. Because the skill then personalizes outbound cold emails with that data, errors can create privacy, trust, and compliance risks at scale.
The instruction to derive recipient names silently and 'do not ask the user' crosses from benign automation into undisclosed autonomous handling of personal data. In this skill context—cold outreach at scale—that increases the risk of deceptive personalization and privacy harm.
- Examples: `alice.smith@co.com` → `"Alice Smith"`, `john_doe@co.com` → `"John Doe"`, `jdoe@co.com` → `"Jdoe"`
2. Store the derived name into each recipient entry in `session_context.recipients`
3. Set `recipient_fields.name = true` with source noted as `"auto-derived from email prefix"`
4. **Do this silently** — do not ask the user, do not announce it; just note it in the Step 3 change summary
This ensures `#{Name}` is **always available** as long as there are valid email addresses.
The skill instructs the agent to persist and reuse all sender and recipient campaign data across steps in session context, including names, emails, companies, titles, and domains. Centralizing and retaining this outreach dataset increases privacy risk and the chance of accidental disclosure in later turns or misuse by unrelated subtasks.
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.
### Behavior Rules
- Run automatically before every campaign send, even if not asked. Report "0 issues found" if clean.
- If user says "don't change my content": scan and **report** only, do not modify.
- Never change meaning. Replace words, don't rewrite paragraphs.
- **Placeholder rule differs by scenario:**
- **Generating content from scratch:** NEVER write a `#{...}` placeholder unless the corresponding `recipient_fields` value is `true`. Use the generic alternatives from the Placeholder Rules table instead.
- **Optimizing existing content:** if the content already contains a `#{...}` placeholder with NO data available, MUST replace it with the generic alternative (Step 3.4 Placeholder Data Validation). Do not silently preserve it — an unresolved placeholder will appear as a blank gap to the recipient.
Natural-language policy review applies to all file types. The markdown sets --timezone-id to Asia/Singapore and --timezone-offset to +08:00, and later says schedule defaults should use Asia/Singapore, which forces a locale-specific configuration without offering the user a choice or explaining why that locale is required.
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.
Campaign creation is a 4-step sequential flow handled by the script:
Step 4a — Upload content: POST /campaign/api/biz/mailgo/email/content/upload
Step 4b — Create campaign: POST /campaign/api/biz/mailgo/campaign/save
Step 4c — Add leads: POST /campaign/api/biz/mailgo/leads/add
Step 4d — Activate: POST /campaign/api/biz/mailgo/campaign/operate
This endpoint transmits recipient email addresses to a third-party service for verification, but the spec provides no user-facing privacy notice or consent boundary. Email addresses are personal/contact data, so silent transmission can violate user expectations, compliance requirements, or organizational data-handling policies.
Uploading full HTML email content to a remote service can expose sensitive business copy, embedded links, tracking logic, or personalized content without the user's clear awareness. The lack of disclosure is risky because users may assume drafting occurs locally while the entire body is actually transferred off-platform.
Defaulting campaign schedules to Asia/Singapore without user opt-in can cause emails to be sent at unintended local times, potentially increasing spam complaints, harming campaign performance, or violating organizational sending expectations. In an automated outreach skill, silent scheduling defaults are operationally risky because they can trigger external actions at scale.
The same operation used for routine campaign state changes can also permanently delete a campaign via a numeric status value, but the spec gives no warning or confirmation guidance. This creates a meaningful risk of accidental destructive actions, especially for an agent that may map natural-language instructions imperfectly to enum values.
The API exposes a capability to read the full plaintext body of reply emails, which is materially more sensitive than aggregate campaign management or reporting. Even if useful for outreach workflows, this grants access to potentially confidential communications and increases the risk of over-collection, insider misuse, or unintended disclosure if invoked without narrow user intent and consent.
The prompt directs the assistant to upload content, create the campaign, add leads, and activate sending in a fixed sequence without an explicit user confirmation immediately before the send-enabling steps. In a cold-email tool, this can cause unintended mass outreach, compliance issues, reputational damage, and unauthorized contact of recipients if prior assumptions or imported lead data are wrong.
The manifest describes verifying recipients, claiming a mailbox, generating content, creating campaigns, managing lifecycle, and viewing reports. Line L181 adds a separate capability to fetch email reply content, which goes beyond the stated reporting/lifecycle scope and is not otherwise justified in the manifest description.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
## Global Rules
1. Always call Actions — never ask users to run scripts or make API calls manually
2. Verify emails before sending to >10 recipients
3. Always run Step 3 optimization before sending (report "0 issues" if clean)
4. Always confirm before delete
No suspicious patterns detected.