Back to skill

Security audit

Send Email

Security checks for vulnerabilities and agentic risk

Overview

This email-sending skill is mostly aligned with its purpose, but it handles email account secrets and a hardcoded default sender in ways users should review carefully before installing.

Install only if you are comfortable giving the agent SMTP credentials and letting it send emails and attachments externally. Prefer a user-owned, narrowly scoped app password or SMTP token entered through a secure secret mechanism, avoid the built-in default sender account, do not use `--no-tls`, and review recipients, attachments, and content before confirming any send.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_email.py:287
Finding
SMTP Credentials Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_email.py:287-293`; documented usage in `SKILL.md:335-342` **Vulnerability Type**: Sensitive credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument('--smtp-server', required=True, help='SMTP server hostname') parser.add_argument('--smtp-port', type=int, required=True, help='SMTP server port') parser.add_argument('--username', required=True, help='SMTP username') parser.add_argument('--password', required=True, help='SMTP password') parser.add_argument('--from-addr', help='Sender email address (default: username)') ``` The documented execution pattern directly places the secret in the command line: ```bash python3 scripts/send_email.py \ --to recipient@example.com \ --subject "Email Subject" \ --content "Email body content" \ --smtp-server smtp.gmail.com \ --smtp-port 587 \ --username your@email.com \ --password your-password-or-app-password ``` ### Technical Analysis The program requires SMTP passwords, authorization codes, or provider API keys through the `--password` command-line argument. Command-line arguments are not an appropriate secret-transport mechanism because they can be exposed through: - Shell history files. - Process inspection utilities and operating-system process metadata. - Command logging, terminal recording, and audit systems. - Agent execution traces or orchestration logs. - Diagnostic output that records complete command invocations. The affected value may be an SMTP authorization code, an account password, or an API key, depending on the selected provider. Although the program does not deliberately print the password, accepting it through `argparse` creates exposure before the application processes it. ### Attack Path 1. A user follows the documented command format and supplies a real SMTP password or API key using `--password`. 2. The shell records the complete comm ...[truncated 831 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the required `--password` argument. - Obtain the password through `getpass.getpass()` so it is not echoed or stored in shell history. - Support reading the secret from a protected file descriptor, operating-system keyring, or dedicated secret-management service. - If noninteractive use is required, accept the name of a secret or credential source rather than the secret itself. - Avoid environment variables where stronger secret-delivery mechanisms are available, because environment data can also leak through diagnostics and process inspection. - Ensure orchestration and agent logs redact credentials and never emit complete secret-bearing commands. - Update all examples in `SKILL.md` so they do not encourage placing real credentials in command text. - Recommend narrowly scoped, revocable SMTP credentials instead of primary account passwords. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_email.py:299
Finding
Plaintext SMTP Authentication Can Be Explicitly Enabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_email.py:299-300, 348, 361-364` **Vulnerability Type**: Transmission of credentials and message contents without transport encryption **Risk Level**: High ### Vulnerable Code ```python parser.add_argument('--attach', action='append', help='File attachment (can be used multiple times)') parser.add_argument('--no-tls', action='store_true', help='Disable STARTTLS') parser.add_argument('--use-ssl', action='store_true', help='Use SSL instead of STARTTLS') ``` ```python success = send_email( to=args.to, subject=args.subject, content=content, smtp_server=args.smtp_server, smtp_port=args.smtp_port, username=args.username, password=args.password, from_addr=args.from_addr, from_name=args.from_name, content_type=content_type, attachments=args.attach, use_tls=not args.no_tls, use_ssl=args.use_ssl, ) ``` ```python else: context = ssl.create_default_context() with smtplib.SMTP(smtp_server, smtp_port) as server: if use_tls: server.starttls(context=context) server.login(username, password) server.send_message(msg) ``` ### Technical Analysis When `--no-tls` is supplied without `--use-ssl`, `use_tls` becomes false and the application establishes an ordinary SMTP connection. It then calls `server.login(username, password)` and sends the message without first negotiating TLS. SMTP authentication commonly uses mechanisms that only encode credentials rather than encrypting them. Consequently, a network observer or malicious SMTP endpoint may recover the username and password. The email body and attachments are also transmitted without transport confidentiality. The application does not restrict this mode to loopback testing, warn the user about credential exposure, or require a separate high-friction confirmation. ### Attack Path 1. A user or automated agent invokes the script with `--no-tls`, whether intention ...[truncated 1126 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove support for authentication over plaintext SMTP. - Require either validated STARTTLS or implicit TLS before calling `server.login()`. - Fail closed if TLS negotiation is unavailable or rejected. - Keep `ssl.create_default_context()` and certificate verification enabled. - If plaintext SMTP is required for local development, restrict it to loopback addresses and prohibit authentication in that mode. - Validate combinations of `--no-tls` and `--use-ssl` rather than allowing ambiguous connection settings. - Display a clear error instead of silently continuing when encryption is disabled. - Add automated tests confirming that authentication cannot occur before a verified TLS channel is established. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Third-Party Dependency Is Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-2` **Vulnerability Type**: Unbounded and non-reproducible third-party dependency resolution **Risk Level**: Medium ### Vulnerable Code ```text # Email sending dependencies markdown>=3.4.0 ``` The installation instruction in `SKILL.md` executes: ```bash pip install -r requirements.txt ``` ### Technical Analysis The requirement accepts every future `markdown` release at or above version 3.4.0. It does not specify an audited version, upper bound, package hash, or locked transitive dependency set. As a result, installation behavior can change over time without any modification to this project. A future compromised, malicious, or incompatible release could be selected automatically. Python package installation and import both execute package-controlled code, so dependency compromise can affect the local environment in which the Skill runs. No evidence was found that the currently named package is malicious. The issue is the absence of controls that ensure installations use the specific dependency artifact that was reviewed. ### Attack Path 1. A user follows the project instructions and runs `pip install -r requirements.txt`. 2. The package resolver selects the newest release satisfying `markdown>=3.4.0`. 3. A future compromised or otherwise unsafe release is downloaded because no exact version or artifact hash is enforced. 4. Package-controlled code executes during installation or when `import markdown` runs. 5. The compromised package gains the permissions of the user running the installation or email script. ### Impact Assessment A compromised dependency would execute with the privileges of the installing or invoking user. It could access email contents, SMTP credentials available to the process, readable local files, and network resources. It could also modify the Python environment. The actual impact depends on the execution account's permissions and the behavior of the select ...[truncated 28 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the dependency to a specific reviewed version, for example with an exact `==` constraint. - Generate and verify cryptographic hashes using a locked requirements file and `pip install --require-hashes`. - Install from the official package index over TLS and avoid unreviewed alternative indexes. - Use a dependency-locking workflow that records resolved transitive dependencies. - Integrate vulnerability and package-provenance scanning into updates. - Review and test dependency upgrades before changing the lock file. - Run installation and execution in a minimally privileged virtual environment or container. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Ssd 3

High
Confidence
99% confidence
Finding
The skill explicitly tells the agent to solicit credentials for a built-in default sender account. This is dangerous because it normalizes secret collection in chat and may facilitate unauthorized use of a shared or non-user-owned mailbox, especially given the adversarial risk of hardcoded operational identities in skills.

Ssd 3

High
Confidence
98% confidence
Finding
The examples repeatedly instruct users to paste passwords, app passwords, and SMTP secrets directly into chat. In most agent systems, chat is not an appropriate secret-entry channel because prompts, transcripts, telemetry, or logs may retain those credentials and expose downstream accounts.

Ssd 3

High
Confidence
99% confidence
Finding
The example conversation demonstrates asking the user for the authorization code of the default agent mailbox, which directly trains the agent to collect and handle mailbox secrets in chat. Examples are operational guidance; here they reinforce insecure behavior and make accidental credential exfiltration more likely.

Ssd 3

High
Confidence
99% confidence
Finding
This second example repeats the insecure pattern of requesting the authorization code for the default sender after gathering content. Repetition across examples increases the likelihood the behavior is implemented consistently and exposes users to credential theft or misuse at scale.

Lp3

Medium
Category
MCP Least Privilege
Confidence
76% confidence
Finding
The skill advertises capabilities that can read local files for attachments/templates but does not declare any tool scope or permissions boundaries. In an agent environment, this weakens reviewability and can enable unintended file access when the skill is invoked with user-supplied paths.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill omits a clear warning that email content and attachments are transmitted to external SMTP providers and recipients. Users may unknowingly send sensitive local files or confidential data outside the current system boundary.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The documentation directs the agent to default to a built-in sender address and then ask the user for credentials for that mailbox, implying operation of an account the user may not control. This can lead to credential harvesting, unauthorized account use, or users being tricked into supplying secrets for a third-party mailbox.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**IMPORTANT - Default Sender Email Behavior**:

**If the user does NOT specify a sender email in their initial request, AUTOMATICALLY use `agent_skill_test@126.com` as the default sender. DO NOT ask the user which email to send from.**

Only ask the user for a different sender email if they explicitly mention wanting to use their own email address.
Confidence
82% confidence
Finding
The instruction to automatically choose a sender identity without asking the user creates unauthorized autonomous decision-making for an externally visible action. In this context, the autonomy is more dangerous because it combines with a hardcoded mailbox and can cause emails to be sent from an unexpected identity or pressure users into providing credentials for that identity.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill instructs collection of highly sensitive passwords, app passwords, API keys, and authorization codes without warning users about the sensitivity of those secrets or safer handling practices. In a chat-based agent context, prompting users to paste credentials directly is especially dangerous because transcripts may be logged, retained, or exposed to other components.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
Earlier guidance says that if the user does not specify a sender email, the skill must automatically use `agent_skill_test@126.com` and must not ask which email to send from. In Example 1, the user omits the sender, but the skill asks for a sender email anyway, directly conflicting with the documented interaction policy.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
Examples 2 and 3 switch the assistant's interaction entirely into Chinese, but the document does not state that language selection is user-driven or optional. This can violate language/locale policy when a skill implicitly forces a language rather than explicitly matching or offering the user's preference.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Email sending dependencies
markdown>=3.4.0
Confidence
93% confidence
Finding
The dependency is specified as `markdown>=3.4.0`, which allows any newer release to be installed and makes builds non-reproducible. This increases supply-chain risk and can silently pull in vulnerable or incompatible versions over time, especially relevant in a skill that may process untrusted email/template content.

Unverifiable Dependency: markdown has 2 known advisory(ies) (CVE-2025-69534 (Python-Markdown has an Uncaught Exception); CVE-2025-69534 (Python-Markdown version 3.8 contain a vulnerability where malformed HTML-like se)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding
The manifest references `markdown` without pinning to a specific version, while known advisories exist for some releases. Because the installed version is unconstrained above 3.4.0, the environment may resolve to an affected release, which is more concerning here because markdown processing in an email-sending skill could be exposed to untrusted template or message content and trigger denial-of-service or parsing issues.

Static analysis

No suspicious patterns detected.