Back to skill

Security audit

Generic Mail Client

Security checks for vulnerabilities and agentic risk

Overview

This mail skill appears purpose-aligned, but it needs review because it can read, send, and change email using stored credentials without adequate sending limits or credential protection.

Install only for a tightly controlled mailbox, preferably a dedicated automation account with an app-specific password. Review and patch dependencies, regenerate the lockfile from an HTTPS registry, move secrets out of config.yaml, and add explicit recipient, payload, rate, and confirmation controls before using it with real email accounts.

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)

T08 · Insecure Dependencies

Warning
Location
package-lock.json:22
Finding
Dependencies Are Locked to an Unencrypted Third-Party Package Mirror<![CDATA[ ## Vulnerability Details **File Location**: `package-lock.json:22-26` and equivalent `resolved` entries throughout `package-lock.json` **Vulnerability Type**: Insecure dependency source **Risk Level**: Medium ### Vulnerable Code ```json "node_modules/@pinojs/redact": { "version": "0.4.0", "resolved": "http://mirrors.tencentyun.com/npm/@pinojs/redact/-/redact-0.4.0.tgz", "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==" } ``` The same unencrypted mirror is used for the other direct and transitive dependencies in the lockfile. ### Technical Analysis The lockfile retrieves dependency archives over plain HTTP from a third-party mirror. HTTP does not authenticate the package server and does not protect package downloads from interception or modification in transit. The SHA-512 integrity fields substantially reduce direct package-substitution risk when the lockfile is trusted and the package manager correctly enforces integrity verification. However, the source remains unauthenticated, exposes dependency requests to network observers, permits denial-of-service or downgrade interference, and becomes a code-execution risk if the lockfile is also modified, integrity checking is bypassed, or the installation workflow accepts regenerated metadata from the compromised mirror. Because dependency code executes with the permissions of the installation and Skill runtime, dependency-source trust is part of the security boundary. ### Attack Path 1. A developer or deployment system runs `npm install` or `npm ci`. 2. The package manager requests archives from `http://mirrors.tencentyun.com`. 3. An attacker with network-path or mirror control intercepts or disrupts the HTTP response. 4. With an unchanged trusted lockfile and enforced integrity checking, unauthorized replacement should fail verification, resulting primarily in installation failure. 5. If the attacker can also alter or regenerate t ...[truncated 622 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Configure npm to use an authenticated HTTPS registry, preferably `https://registry.npmjs.org/` or an organization-controlled HTTPS artifact repository. 2. Delete and regenerate `package-lock.json` using the trusted HTTPS registry. 3. Verify that every `resolved` dependency URL uses HTTPS. 4. Use `npm ci` in CI and production so the reviewed lockfile is not silently regenerated. 5. Keep integrity verification enabled and reject installation when a package hash differs. 6. Restrict lockfile modifications through code review and protected branches. 7. Consider dependency provenance verification, automated vulnerability scanning, and an internally approved package allowlist. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/mailClient.ts:32
Finding
Email Sending Lacks the Documented Anti-Abuse and Payload Limits<![CDATA[ ## Vulnerability Details **File Location**: `src/mailClient.ts:32-67`; related request definition at `src/types.ts:40-51` **Vulnerability Type**: Missing rate, recipient, and payload controls **Risk Level**: Medium ### Vulnerable Code ```ts async sendEmail(req: SendEmailRequest): Promise<SendEmailResponse> { const acc = this.getAccount(req.accountId); const smtp = acc.smtp; const transporter = nodemailer.createTransport({ host: smtp.host, port: smtp.port, secure: smtp.useTLS, auth: { user: acc.auth.username, pass: acc.auth.password, }, }); const message = { from: acc.auth.username, to: req.to.join(","), cc: req.cc?.length ? req.cc.join(",") : undefined, bcc: req.bcc?.length ? req.bcc.join(",") : undefined, subject: req.subject, text: req.bodyText, html: req.bodyHtml, attachments: (req.attachments || []).map((att) => ({ filename: att.filename, content: Buffer.from(att.contentBase64, "base64"), contentType: att.mimeType, })), }; const info = await transporter.sendMail(message); return { status: "ok", accountId: req.accountId, messageId: info.messageId, sentAt: new Date().toISOString(), }; } ``` The request schema also permits unrestricted arrays and base64 payloads: ```ts export interface SendEmailRequest { accountId: string; to: string[]; cc?: string[]; bcc?: string[]; subject: string; bodyText?: string; bodyHtml?: string; attachments?: { filename: string; contentBase64: string; mimeType?: string; }[]; } ``` ### Technical Analysis The documentation states that default sending-frequency and listing limits prevent misuse as a spam tool. The implementation caps list results but does not enforce any sending-frequency limit. The sending handler accepts arbitrary recipient arrays, unrestricted external addresses, unbounded body content, and unbounded base64 attachments. It immediately converts attac ...[truncated 1781 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce per-account and global rate limits using a persistent, concurrency-safe limiter. 2. Set maximum counts for To, Cc, Bcc, and total recipients. 3. Validate all email addresses and reject malformed or header-injection content. 4. Set maximum subject, text, HTML, individual attachment, aggregate attachment, and total message sizes before decoding base64. 5. Reject malformed base64 and limit the number of attachments. 6. Apply destination allowlists or domain policies for automation-only mailboxes. 7. Require explicit user confirmation for bulk mail, Bcc use, external recipients, or sensitive attachments. 8. Add account-level permissions so accounts can be configured as send-only, read-only, or restricted to approved operations. 9. Record security-safe audit metadata such as account ID, recipient count, destination domains, payload size, timestamp, and result without logging message bodies, credentials, or attachment contents. 10. Update `SKILL.md` so its security claims exactly match implemented controls. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.ts:12
Finding
Mailbox Credentials Are Loaded from a Project-Local Plaintext Configuration File<![CDATA[ ## Vulnerability Details **File Location**: `src/index.ts:12-17`; credential fields at `config.yaml:18-21` and `config.yaml:40-43` **Vulnerability Type**: Plaintext sensitive-data storage **Risk Level**: Medium ### Vulnerable Code ```ts let skillConfig: SkillConfig; if (fs.existsSync(configPath)) { skillConfig = yaml.load(fs.readFileSync(configPath, "utf8")) as SkillConfig; } else { throw new Error("generic-mail-client: config.yaml not found. Please copy config.example.yaml to config.yaml and fill in credentials."); } ``` The bundled configuration structure stores passwords directly in YAML: ```yaml auth: username: "test@example.com" password: "test-password" # Recommended use: application-specific password ``` A second account follows the same pattern: ```yaml auth: username: "yourname@gmail.com" password: "test-password" ``` The observed values appear to be placeholders rather than confirmed active credentials. The vulnerability is the required storage pattern: operators are instructed to replace these values with operational credentials in a project-local plaintext file. ### Technical Analysis The Skill reads `config.yaml` synchronously from its installation directory and retains the parsed account objects, including passwords, in process memory. No secret-manager integration, environment indirection, encryption, permission validation, or repository-exclusion control is present in the reviewed project. The handlers do not directly return passwords to the LLM, so the claim that credentials are not exposed through handler responses is materially supported. Nevertheless, plaintext storage increases exposure through source-control commits, archived Skill packages, backups, filesystem access, diagnostics, or accidental sharing. ### Attack Path 1. An operator copies the example configuration to `config.yaml`. 2. The operator replaces placeholder passwords with real mailbox or application-specific passwords. 3. The plaintext fil ...[truncated 1009 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store mailbox passwords in a host secret manager, operating-system credential store, or deployment-platform secret facility. 2. Keep only non-sensitive account identifiers, protocol choices, endpoints, and limits in YAML. 3. Reference secrets indirectly, for example through a secret identifier resolved by the host at runtime. 4. If environment variables are used, inject them at deployment time and avoid committing them to files or process-launch scripts. 5. Add `config.yaml` to `.gitignore`, package-exclusion rules, backup exclusions, and secret-scanning policies. 6. Validate restrictive filesystem permissions before loading any fallback secret file. 7. Use dedicated automation mailboxes and application-specific credentials rather than personal mailbox passwords. 8. Rotate any credential that has previously been committed, packaged, logged, or shared; removing it from the latest revision is insufficient. 9. Minimize the runtime lifetime of secret values and ensure errors and diagnostics never serialize the complete configuration object. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (29)

Known Vulnerable Dependency: nodemailer==8.0.1 — 10 advisory(ies): CVE-2026-82661 (Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary); GHSA-2x7j-588g-ccc2 (Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote den); GHSA-8m3c-c648-2xjj (Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disable) +7 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
The lockfile includes imapflow-bundled nodemailer 8.0.1, which static analysis identifies as carrying multiple known vulnerabilities including header injection and denial-of-service issues. In a mail-client skill, a vulnerable mail transport/parser library is especially sensitive because it may process attacker-controlled email addresses, headers, and message content.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
82% confidence
Finding
The project pulls in ip-address 10.1.0 via socks, and the listed advisories indicate parsing inconsistencies and an HTML/XSS issue. In this skill context the XSS vector is less likely unless address data is rendered into HTML, but parser discrepancies can still matter if proxy or network address validation relies on this library.

Known Vulnerable Dependency: js-yaml==4.1.1 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
93% confidence
Finding
The lockfile includes js-yaml 4.1.1, which is flagged for multiple CPU-exhaustion issues involving crafted YAML structures. If the skill accepts or loads YAML from user-controlled, remote, or repository-provided input, an attacker could trigger denial of service by supplying pathological YAML documents.

Known Vulnerable Dependency: nodemailer==6.10.1 — 12 advisory(ies): CVE-2026-82661 (Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary); GHSA-2x7j-588g-ccc2 (Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote den); GHSA-8m3c-c648-2xjj (Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disable) +9 more

High
Category
Supply Chain
Confidence
97% confidence
Finding
The top-level nodemailer 6.10.1 dependency is a true vulnerability because it is directly used by a mail-client skill and is associated with multiple known issues including CRLF/header injection and resource-consumption problems. This context increases risk: email composition and transport often involve attacker-influenced fields, so exploitation could lead to message/header manipulation, policy bypass, or service disruption.

Known Vulnerable Dependency: js-yaml==4.1.1 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
99% confidence
Finding
The resolved js-yaml version is reported as having multiple known advisories, including CPU-exhaustion style parsing issues. In a mail-related skill, YAML processing may be reachable through configuration or content handling paths, so vulnerable parsing can enable denial of service or resource exhaustion if untrusted YAML is ever processed.

Known Vulnerable Dependency: nodemailer==6.10.1 — 12 advisory(ies): CVE-2026-82661 (Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary); GHSA-2x7j-588g-ccc2 (Nodemailer: Quadratic (O(n²)) time complexity in addressparser allows remote den); GHSA-8m3c-c648-2xjj (Nodemailer: resolveContent() on a MailMessage bypasses disableFileAccess/disable) +9 more

High
Category
Supply Chain
Confidence
99% confidence
Finding
The resolved nodemailer version is flagged with numerous known vulnerabilities, including header injection, parser complexity, and content-resolution bypass issues. In a generic mail client skill this package is core functionality, so the context makes the risk more serious because email addresses, headers, attachments, and message content are likely attacker-influenced inputs.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The skill description is written entirely in Chinese and presents the skill as a generic mail client, but it does not indicate that language choice is optional or limited to a Chinese-speaking context. For a generic skill, this creates a locale-policy concern because it implicitly constrains usage to a specific language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This YAML file contains user-facing natural-language content in Chinese, including comments and account display names, with no indication that the skill supports other languages or that the locale restriction is intentional and justified. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This manifest contains user-facing natural-language strings such as "阿里云企业邮箱" and "Gmail 个人" along with Chinese-only comments, which indicates a fixed locale choice. The file does not document that the skill is intended only for Chinese-speaking users or provide any language/locale choice, which can violate language/locale policy requirements.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The sendEmail handler performs a potentially impactful external action by transmitting data over email, but this file provides no confirmation prompt, logging, comment, or docstring warning about that behavior. For a code file, outbound communication of user or system data should have some visible disclosure unless such warning is documented elsewhere.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This method sends outbound email, including recipients, subject, body, and attachments, over SMTP, but the code provides no confirmation prompt, visible log/print, or explanatory comment warning that user data will be transmitted. For a code file, network transmission of user data is safety-relevant and should include some form of disclosure unless clearly surfaced elsewhere.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The IMAP helper connects to a remote mail server using account credentials and is used to fetch message metadata and content, but there is no user-facing notice, confirmation, or explanatory comment disclosing this network access to potentially sensitive mailbox data. Accessing remote mailbox contents is privacy-sensitive and should not be silent in code absent other visible warnings.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This method modifies mailbox state by marking messages read/unread and moving messages between folders, but the code includes no confirmation, visible log, or warning comment explaining that it changes remote email state. These actions can affect user data organization and should be disclosed before or during execution.

Vague Triggers

Medium
Confidence
91% confidence
Finding
This file is a JSON manifest-type file, so vague-trigger checks apply. The only descriptive identifier is the broad skill name "generic-mail-client-skill," and the manifest provides no invocation phrases, context limits, or exclusion conditions, making activation scope unspecified and potentially overly broad.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The sendEmail handler invokes the mail client to send email, which is a network action that may transmit user-provided content externally. In this code, there is no confirmation prompt, logging, comment, or docstring warning the user that the skill will send outbound email.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This method sends outbound email, including recipients, subject, body, and attachments, over the network via SMTP. The code contains no confirmation prompt, user-visible log/print, or explanatory comment/docstring warning that user data and attachment contents will be transmitted.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
The IMAP helper connects to a mail server using account credentials and is then used by message-listing and message-fetching flows to retrieve mailbox metadata and message content. There is no confirmation prompt, user-visible logging, or descriptive comment/docstring warning that private mailbox data will be accessed over the network.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This method marks messages read/unread and can move messages to another folder, which changes remote mailbox state and may be difficult to undo. The code includes no confirmation, print/log notice, or descriptive warning comment/docstring about these potentially destructive mailbox modifications.

Missing User Warnings

Medium
Confidence
82% confidence
Finding
This TypeScript file defines an auth object containing username and password fields for mail account configuration. Because this is a code file handling sensitive credentials and there is no nearby comment, docstring, or other user-facing disclosure explaining the sensitivity or expected handling, it meets the missing-warning criterion for credential access.

Missing User Warnings

Low
Confidence
73% confidence
Finding
The code reads configuration from config.yaml and initializes a mail client with filled-in credentials, as indicated by the error message requesting credentials. Accessing and using credentials is a safety-relevant operation, but this file contains no visible warning, comment, or user-facing disclosure about credential use.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"build": "tsc -p ."
  },
  "dependencies": {
    "imapflow": "^1.0.0",
    "js-yaml": "^4.1.0",
    "nodemailer": "^6.9.0"
  },
Confidence
92% confidence
Finding
The dependency is specified with a caret range, which allows newer semver-compatible versions to be installed over time. This weakens build reproducibility and can unexpectedly introduce vulnerable or incompatible transitive code if the dependency supply chain changes.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "imapflow": "^1.0.0",
    "js-yaml": "^4.1.0",
    "nodemailer": "^6.9.0"
  },
  "devDependencies": {
Confidence
98% confidence
Finding
The js-yaml dependency uses a caret range, so installs may float to later releases without explicit review. In this file context that is more dangerous because js-yaml is also separately identified as landing on a version with known advisories, increasing the chance of pulling a vulnerable build.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"dependencies": {
    "imapflow": "^1.0.0",
    "js-yaml": "^4.1.0",
    "nodemailer": "^6.9.0"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
Confidence
98% confidence
Finding
The nodemailer dependency is unpinned, allowing semver-compatible releases to be installed automatically. That creates supply-chain and reproducibility risk, and here it is more significant because the resolved version is also flagged as having multiple known vulnerabilities.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"nodemailer": "^6.9.0"
  },
  "devDependencies": {
    "typescript": "^5.0.0",
    "@types/node": "^18.0.0",
    "@types/js-yaml": "^4.0.0",
    "@types/nodemailer": "^6.4.0"
Confidence
88% confidence
Finding
The TypeScript compiler dependency is unpinned with a caret range, which can lead to non-reproducible builds and unexpected toolchain behavior. As a devDependency this is generally less directly exploitable at runtime, but it still affects build integrity and supply-chain hygiene.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "devDependencies": {
    "typescript": "^5.0.0",
    "@types/node": "^18.0.0",
    "@types/js-yaml": "^4.0.0",
    "@types/nodemailer": "^6.4.0"
  }
Confidence
86% confidence
Finding
The @types/node package is unpinned, which may cause inconsistent builds or type-resolution changes across environments. Since it is a development-only typing package, the direct runtime security impact is low, but it still represents weak dependency control.

Static analysis

No suspicious patterns detected.