Back to skill

Security audit

Mufi Email Manager

Security checks for vulnerabilities and agentic risk

Overview

This email skill is mostly purpose-aligned, but it handles mailbox credentials and can send email while its documentation overstates available features and lacks enough controls for high-impact email actions.

Install only if you are comfortable giving it email account credentials and mailbox access. Treat reply and scheduled examples carefully because they can affect real recipients; use app-specific passwords, limit configured accounts, avoid unattended cron use until controls are added, and review the missing/overstated commands before relying on it.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/config.js:16
Finding

SMTP STARTTLS Is Not Enforced for Gmail and Naver Connections

Content
View full analysis

Vulnerability Details

File Location: scripts/lib/config.js:16-22, scripts/lib/config.js:35-41, and scripts/lib/smtp-client.js:9-11
Vulnerability Type: Opportunistic TLS permits a potential SMTP downgrade
Risk Level: Medium

Vulnerable Code

js
// scripts/lib/config.js:16-22
smtp: {
  host: process.env.GMAIL_SMTP_HOST || 'smtp.gmail.com',
  port: parseInt(process.env.GMAIL_SMTP_PORT) || 587,
  secure: false, // STARTTLS
  auth: {
    user: process.env.GMAIL_USER,
    pass: process.env.GMAIL_PASS
  }
}
js
// scripts/lib/config.js:35-41
smtp: {
  host: process.env.NAVER_SMTP_HOST || 'smtp.naver.com',
  port: parseInt(process.env.NAVER_SMTP_PORT) || 587,
  secure: false, // STARTTLS
  auth: {
    user: process.env.NAVER_USER,
    pass: process.env.NAVER_PASS
  }
}
js
// scripts/lib/smtp-client.js:9-11
async connect() {
  this.transporter = nodemailer.createTransport(this.config);
  await this.transporter.verify();
}

Technical Analysis

Gmail and Naver use SMTP port 587 with secure: false, which is the expected initial configuration for a STARTTLS connection. However, the Nodemailer transport does not set requireTLS: true.

Without requireTLS, encryption is opportunistic rather than mandatory. If the SMTP server does not advertise STARTTLS—whether because of a malicious server, DNS or host redirection, or an on-path STARTTLS-stripping attack—the client may continue without guaranteeing that the connection has been upgraded before authentication.

The same transport contains the email username and password. Consequently, failure to enforce TLS can expose authentication data and outgoing message content if the connection is downgraded or directed to an untrusted endpoint. The risk is increased because the SMTP host can be overridden through environment variables.

Attack Path

  1. A victim configures a Gmail or Naver account an ...[truncated 1209 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require STARTTLS for all port 587 transports:

    js
    smtp: {
      host: process.env.GMAIL_SMTP_HOST || 'smtp.gmail.com',
      port: parseInt(process.env.GMAIL_SMTP_PORT) || 587,
      secure: false,
      requireTLS: true,
      tls: {
        rejectUnauthorized: true,
        minVersion: 'TLSv1.2'
      },
      auth: {
        user: process.env.GMAIL_USER,
        pass: process.env.GMAIL_PASS
      }
    }
    
  2. Apply the same configuration to the Naver SMTP transport.

  3. Reject any authenticated SMTP configuration that uses neither direct TLS nor mandatory STARTTLS.

  4. Validate overridden SMTP hosts against an explicit allowlist unless custom mail servers are an intentional supported feature.

  5. Prefer provider-specific application passwords or narrowly scoped tokens instead of primary account passwords.

  6. Add integration tests confirming that connection establishment fails when STARTTLS is unavailable or certificate validation fails.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/imap-client.js:49
Finding

Unbounded Email and Attachment Buffering Allows Remote Memory Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/lib/imap-client.js:49-96
Vulnerability Type: Unbounded processing of attacker-controlled email content
Risk Level: Medium

Vulnerable Code

js
async fetchMessages(uids, options = {}) {
  if (!uids || uids.length === 0) return [];

  const messages = [];
  const fetch = this.imap.fetch(uids, {
    bodies: '',
    struct: true,
    ...options
  });

  return new Promise((resolve, reject) => {
    fetch.on('message', (msg, seqno) => {
      let buffer = '';
      let attrs = null;

      msg.on('body', (stream) => {
        stream.on('data', (chunk) => {
          buffer += chunk.toString('utf8');
        });
      });

      msg.once('attributes', (a) => {
        attrs = a;
      });

      msg.once('end', async () => {
        try {
          const parsed = await simpleParser(buffer);
          messages.push({
            uid: attrs.uid,
            flags: attrs.flags,
            date: attrs.date,
            subject: parsed.subject,
            from: parsed.from?.text || '',
            to: parsed.to?.text || '',
            text: parsed.text || '',
            html: parsed.html || '',
            attachments: parsed.attachments || []
          });
        } catch (err) {
          console.error(`Error parsing message ${seqno}:`, err.message);
        }
      });
    });

    fetch.once('error', reject);
    fetch.once('end', () => resolve(messages));
  });
}

Technical Analysis

The IMAP client requests bodies: '', causing each selected email to be downloaded in full. Every data chunk is appended to an unbounded JavaScript string before the complete message is passed to simpleParser.

Parsing creates additional in-memory representations for the plain-text body, HTML body, message metadata, and attachments. The resulting attachment buffers are then retained in the messages arr ...[truncated 1952 chars]

Remediation
View remediation

Remediation Suggestions

  1. Fetch only the headers required by listing and classification operations rather than complete messages:

    js
    const fetch = this.imap.fetch(uids, {
      bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE MESSAGE-ID)',
      struct: false
    });
    
  2. Fetch message bodies only when an operation explicitly requires them.

  3. Do not download or retain attachment contents for listing, summary, filtering, or reply-recipient lookup.

  4. Track the number of bytes received and abort the stream when a per-message or aggregate limit is exceeded.

  5. Configure mailparser limits, such as maximum HTML size and attachment handling controls, appropriate to the deployed version.

  6. Stream attachments to controlled storage only when explicitly requested; enforce attachment count and size limits.

  7. Cap concurrent message parsing to prevent aggregate memory spikes.

  8. Record a safe warning and skip oversized messages instead of terminating the entire command.

  9. Add tests using oversized bodies, deeply nested MIME messages, and large attachments to verify that resource limits are enforced.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

설명은 이메일 통합 관리 전반과 자동 답장, 요약, 다이제스트 생성까지 포함한 고수준 기능 세트를 주장하지만, 실제 코드 조각은 IMAP 기반 수신 메일 접근과 검색/상태 변경에 한정된다. 특히 SMTP 관련 발신 기능이 전혀 없으므로 자동 답장은 지원되지 않으며, 메일 내용을 분석해 요약하거나 일일 다이제스트를 생성하는 로직도 없다. 또한 여러 한국형 메일 서비스 통합을 위한 서비스별 설정/처리도 보이지 않는다. 따라서 설명이 코드의 실제 동작 범위를 상당히 과장하고 있어 불일치로 판단된다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

코드는 summary.js 한 조각만 보면 IMAP을 통해 최근 메시지를 조회하고, 읽지 않은 메일을 키워드 기반으로 분류해 요약 출력하는 기능만 수행한다. 이는 선언된 기능 중 '읽지 않은 메일 요약' 및 일부 '키워드 필터링'과는 부합한다. 그러나 설명의 핵심인 Gmail/네이버/다음/카카오 메일의 통합 관리, SMTP 기반 동작, 자동 답장, 일일 다이제스트 생성은 이 코드에서 나타나지 않는다. 또한 실제 동작은 단일 account 옵션을 받아 해당 계정 요약을 출력하는 수준이므로, 선언된 폭넓은 이메일 통합 관리 도구라는 설명과는 범위와 주기능 면에서 차이가 있다.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 92)May include surrounding context.

md
node scripts/check-all.js [--limit 20]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 98)May include surrounding context.

md
node scripts/check.js --account gmail [--limit 10]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 99)May include surrounding context.

md
node scripts/check.js --account gmail [--limit 10]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 107)May include surrounding context.

md
node scripts/summary.js [--account gmail] [--recent 24h]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 135)May include surrounding context.

md
node scripts/filter.js --keywords "결제,청구,승인" [--account all] [--recent 7d]

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 225)May include surrounding context.

md
node scripts/filter.js --keywords "결제,청구,승인" [--account all] [--recent 7d]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/check-all.js (reported line 64)May include surrounding context.

js
const accounts = getAllConfiguredAccounts();

  if (accounts.length === 0) {
    console.error('❌ 설정된 계정이 없습니다. .env 파일을 확인하세요.');
    process.exit(1);
  }

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/lib/config.js (reported line 2)May include surrounding context.

js
const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });

// 계정 설정 정보
const ACCOUNTS = {

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documentation describes use of environment variables for credentials and network access to IMAP/SMTP servers, but it does not declare any explicit tool scope such as allowed tools or permissions. This weakens security review and consent boundaries because a user or platform may not be clearly informed that the skill needs secret access and external network connectivity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises auto-reply and email sending without an explicit warning that these are outbound actions affecting third-party communications. In an email-management context, this is risky because users may trigger messages to real recipients without appreciating the external side effects, leading to data leakage, mistaken communications, or reputational harm.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The cron examples show automated digest sending and notifications but omit a warning that these actions may run unattended and send messages or alerts without human review. In this context, scheduled automation increases the chance of accidental disclosure, spamming, or repeated unintended outbound communications.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

User-facing comments and console messages are written in Korean, and dates are explicitly formatted with toLocaleString('ko-KR'). This imposes a specific language and locale without opt-in, which matches the policy category for language or locale restriction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code connects to each configured IMAP account and fetches unread messages, which involves accessing sensitive user email data. Although the script's purpose is to check unread mail, there is no in-code disclosure or warning that mailbox contents and metadata from all configured accounts will be accessed and displayed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code explicitly formats dates with toLocaleString('ko-KR'), which forces a specific locale in user-visible output. Combined with the Korean-only CLI messages throughout the script, this creates a language/locale constraint without opt-in or a documented region-specific requirement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code explicitly loads a .env file that is expected to contain account credentials, and later uses environment variables such as GMAIL_PASS and NAVER_PASS. In this file there is no user-facing prompt, log, or explanatory comment warning that the skill accesses stored email credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The configuration reads sensitive values like GMAIL_PASS, NAVER_PASS, DAUM_PASS, and KAKAO_PASS to authenticate against email services. Although credential access is central to the feature, this file itself provides no visible disclosure, prompt, or warning that secrets will be read and used.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code establishes an IMAP connection using the supplied configuration, which typically includes email account credentials and access to mailbox contents. While the behavior is core to an IMAP client, this file contains no docstring, comment, or user-facing logging that discloses the sensitive account access being performed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The fetchMessages method downloads and parses full message bodies, headers, and attachments from the user's mailbox, which is privacy-sensitive data access. The code has error logging, but no user-facing disclosure, confirmation, or explanatory comment indicating that full mailbox content will be retrieved.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes integrated email management focused on unread mail summaries, keyword filtering, auto-replies, and daily digests. While email access is expected, these methods actively alter mailbox state via IMAP flags, which is not reflected in the described capabilities of this component and goes beyond passive retrieval/filtering behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This function performs a write operation against the mailbox by adding the \Seen flag, changing message state on the remote server. Aside from a terse inline comment about read-write mode, there is no user-facing warning, confirmation, or explanatory documentation for this state-changing action.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This function modifies remote mailbox state by removing the \Seen flag from messages, which is a write operation with user-visible consequences. The code does not provide any user-facing disclosure or clear documentation about this side effect.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code includes natural-language comments and user-facing console output in Korean, starting with the file description and continuing throughout the script. Because the skill does not offer a language/locale option or explain that it is intentionally Korean-only, it violates the policy against forcing a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This script's natural-language strings and comments are entirely in Korean, including the user-visible status and summary output. Because there is no option to select another language and no documented justification that the skill is Korea-specific, this creates a language/locale policy issue.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.