Back to skill

Security audit

MAMA

Security checks for vulnerabilities and agentic risk

Overview

This is a real mail assistant, but it needs review because it stores mailbox credentials locally and has under-scoped config and cleanup behavior that can affect sensitive data or files.

Install only if you are comfortable giving this skill access to the configured mailboxes. Use a dedicated app password where possible, keep scripts/mail_config.json private, avoid /tmp files for secrets unless permissions are locked down, review any send or move command before it runs, and avoid using custom --output-dir with --cleanup-days.

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/process_digest.py:197
Finding

Caller-Controlled Output Directory Enables Recursive Deletion of Unrelated Files

Content
View full analysis

Vulnerability Details

File Location: scripts/process_digest.py:197-209
Vulnerability Type: Unrestricted recursive file deletion
Risk Level: High

Vulnerable Code

python
def cleanup_outputs(output_dir: Path, days: int) -> int:
    if days < 0 or not output_dir.exists():
        return 0
    cutoff = datetime.now() - timedelta(days=days)
    removed = 0
    for path in output_dir.rglob("*"):
        if not path.is_file():
            continue
        try:
            modified = datetime.fromtimestamp(path.stat().st_mtime)
        except OSError:
            continue
        if modified < cutoff:
            path.unlink()
            removed += 1
    return removed

The affected directory is supplied through a command-line argument:

python
parser.add_argument("--output-dir", default=str(SKILL_DIR / ".temp"))
parser.add_argument(
    "--cleanup-days", type=int, help="Clean historical output files older than N days"
)

Technical Analysis

The cleanup routine recursively enumerates every file beneath output_dir and deletes files based solely on modification time. Although the default output directory is the Skill's .temp directory, --output-dir is caller-controlled and is not resolved or restricted to that directory.

Consequently, cleanup authority is not limited to files created by this Skill. Any directory readable and writable by the Agent process can become the deletion root. The function also does not restrict deletion to expected output filename patterns such as emails_*.json, analysis_*.json, or summary_*.md.

This exceeds the minimum filesystem privileges required for cleaning up generated digest artifacts.

Attack Path

  1. An attacker, malicious instruction, or mistaken automation causes the Agent to invoke process_digest.py.
  2. The invocation supplies a sensitive writable directory through --output-dir.
  3. It also su ...[truncated 917 chars]
Remediation
View remediation

Remediation Suggestions

  1. Resolve the requested directory to a canonical absolute path and require it to remain beneath the Skill-owned .temp directory:

    python
    allowed_root = (SKILL_DIR / ".temp").resolve()
    requested = output_dir.resolve()
    
    if requested != allowed_root and allowed_root not in requested.parents:
        raise ValueError("Cleanup is restricted to the Skill temporary directory.")
    
  2. Refuse filesystem roots, home directories, the project root, and symbolic-link traversal.

  3. Delete only recognized artifacts created by the Skill, using strict filename patterns and expected extensions.

  4. Keep cleanup separate from normal digest processing and require explicit confirmation when a non-default directory is requested.

  5. Record a dry-run list before deletion and provide a --dry-run option.

  6. Where practical, maintain a manifest of generated files and delete only entries from that manifest.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mail_accounts.py:24
Finding

Configuration Loading Executes Arbitrary Python Code

Content
View full analysis

Vulnerability Details

File Location: scripts/mail_accounts.py:24-34
Additional Locations: scripts/analyze_emails.py:61-71, scripts/forward_mail.py:24-34, scripts/init_config.py:263-273
Vulnerability Type: Arbitrary code execution through executable configuration files
Risk Level: Medium

Vulnerable Code

scripts/mail_accounts.py loads legacy mail configuration as an executable Python module:

python
def _load_py_config(path: Path) -> dict[str, Any]:
    if not path.exists():
        return {}
    spec = importlib.util.spec_from_file_location("mail_config", str(path))
    if spec is None or spec.loader is None:
        return {}
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return {key: getattr(module, key) for key in dir(module) if key.isupper()}

scripts/analyze_emails.py uses the same mechanism for the active digest configuration:

python
def load_python_config(path: Path) -> dict:
    if not path.exists():
        return {}
    import importlib.util

    spec = importlib.util.spec_from_file_location("digest_config", str(path))
    if spec is None or spec.loader is None:
        return {}
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return {key: getattr(module, key) for key in dir(module) if key.isupper()}

Technical Analysis

exec_module() executes all top-level statements in the selected Python file. The loader subsequently selecting uppercase variables does not provide isolation because execution has already occurred.

Therefore, mail_config.py and digest_config.py are code-execution surfaces rather than passive configuration files. The risk applies whenever an attacker can replace, modify, or plant one of these files through a compromised archive, shared workspace, unsafe synchronization process, another local vulnerability, or uninte ...[truncated 1511 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace Python configuration files with non-executable formats such as JSON or TOML.
  2. Define an explicit schema and validate field names, types, ranges, and allowed values before use.
  3. Remove spec_from_file_location(), module_from_spec(), and exec_module() from all configuration-loading paths.
  4. Migrate legacy mail_config.py files through a one-time restricted parser rather than importing them.
  5. Convert digest_config.py into a data-only file such as digest_config.json.
  6. If backward compatibility is temporarily unavoidable, parse only literal assignments with Python's AST and reject imports, calls, attribute access, comprehensions, and all other executable syntax. Do not use eval() or module import as a parser.
  7. Verify configuration ownership and permissions before loading it, and reject symbolic links or files writable by untrusted principals.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mail_accounts.py:120
Finding

Mailbox Credentials Are Persisted in Plaintext Without Enforced Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/mail_accounts.py:120-136
Credential Population Location: scripts/init_config.py:153-169, 539-548
Vulnerability Type: Insecure storage of sensitive authentication material
Risk Level: Medium

Vulnerable Code

The initialization process places the supplied client credential directly into the account data:

python
def build_account_config(
    host: str,
    port: int,
    user: str,
    client_value: str,
    smtp_host: str = "",
    smtp_port: int = 465,
    provider: str = "custom",
) -> dict:
    return {
        "mail_provider": provider,
        "mail_user": user,
        "imap_host": host,
        "imap_port": int(port),
        "imap_user": user,
        "imap_client_value": client_value,
        "from_name": "Mailbox Agent",
        "smtp_host": smtp_host,
        "smtp_port": int(smtp_port),
        "smtp_user": "",
        "smtp_client_value": "",
    }

The configuration writer persists the resulting structure as plaintext JSON without setting file permissions:

python
def write_accounts_config(
    path: Path,
    default_account: str,
    accounts: dict[str, dict[str, Any]],
) -> None:
    path.write_text(
        json.dumps(
            {
                "version": 2,
                "default_account": default_account,
                "accounts": accounts,
            },
            ensure_ascii=False,
            indent=2,
        )
        + "\n",
        encoding="utf-8",
    )

Technical Analysis

The IMAP client value is reusable authentication material and is stored directly in scripts/mail_config.json. The write operation relies on ambient process umask and parent-directory permissions; it does not securely create the file with mode 0600, verify ownership, reject symbolic links, or validate permissions when loading it.

The SMTP creden ...[truncated 1770 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer an operating-system credential store, keyring, or secret-management service. Persist only a credential reference in the JSON configuration.

  2. If a local file is required, create it atomically with owner-only permissions rather than relying on Path.write_text():

    python
    import os
    
    flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
    if hasattr(os, "O_NOFOLLOW"):
        flags |= os.O_NOFOLLOW
    
    fd = os.open(path, flags, 0o600)
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as handle:
            json.dump(data, handle, ensure_ascii=False, indent=2)
            handle.write("\n")
    except Exception:
        os.close(fd)
        raise
    
  3. Apply and verify mode 0600 after writes, and verify that the file is owned by the current user.

  4. Reject symbolic links and non-regular files before reading or writing configuration.

  5. Validate permissions on every load and refuse to use a configuration readable or writable by unauthorized principals.

  6. Store sensitive configuration outside the distributable Skill source directory.

  7. Document credential rotation and advise users to revoke credentials immediately if the configuration file is exposed.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (47)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a full-featured multi-account email assistant. However, the provided code chunk is only a metadata file containing a version constant. It does not access email services, process accounts, read or send messages, handle attachments, or generate summaries. Because the actual code shown has a materially different and far narrower purpose than the declared functionality, this is a clear description-behavior mismatch for the supplied chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个完整的多账户邮箱代理/智能体,核心能力应包括连接邮箱服务、对邮件进行读写操作以及跨账号处理约束。实际代码的主功能仅是对输入的邮件 JSON 进行规则分析:匹配关键词、提取可能的截止时间、生成摘要和待办,并输出巡检结果。这只覆盖了声明中的“按关键词和截止时间生成邮件巡检摘要”这一小部分,且还是基于现成输入数据而非真实邮箱访问。代码没有任何 IMAP/SMTP、网络访问、账号状态管理、邮件发送/转发/草稿、已读未读或移动邮件等实现,因此描述明显高估了代码能力,属于实质性不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is for a full-featured multi-account email assistant. The supplied code does not implement email access or message operations at all. Instead, it functions as a local notification adapter: it reads a markdown file, saves notification copies to disk, prints the payload, and emits a channel-related status line. This is a materially different primary purpose and an unrelated capability set compared with the declared mailbox/IMAP/SMTP agent behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

该代码块与声明描述存在明显不匹配。声明描述的是一个功能完整的多账户邮箱智能体/代理,覆盖 IMAP/SMTP 的收取、搜索、阅读、附件处理、回复、转发、发送、状态修改、移动和巡检摘要等一整套能力,并强调多账户一致性策略。而实际代码仅实现了一个“查看并快速转发邮件”的辅助 CLI 工具:读取外部 JSON 中的邮件项、展示正文/附件/链接摘要、接受一个收件人、从本地配置读取 SMTP 账号密码,并尝试发送转发邮件或保存为草稿。它没有实现声明中的大多数核心能力,尤其没有 IMAP 邮箱读取与管理、多账户编排、跨账号约束、邮件搜索或巡检。虽然“转发邮件/显式发送/生成草稿”与声明有局部重叠,但整体主用途和能力范围远小于且不同于声明,因此应判定为描述与代码行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

该代码片段的核心职责是“初始化邮箱智能体配置”:解析命令行参数、规范化邮箱地址、根据域名推断 IMAP/SMTP 主机和端口、从环境变量/文件/stdin/交互输入读取客户端值、将账号写入配置文件、生成 digest_config.py,并可调用 read_emails.py 进行连通性测试。尽管文案中多次提到支持多账户以及邮件智能体的各种能力,但在此代码片段中并未看到这些能力的实际实现;唯一与运行时功能接近的是通过子进程做一次读取脚本验证连接。就“描述是否准确代表所给代码块实际行为”而言,描述讲的是完整邮箱代理产品能力,而代码块只是配置初始化工具,主目的存在显著差异,因此应判定为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

整体上,代码的大部分核心能力与描述相符,包括多账户搜索、读取、附件下载、回复草稿、转发、显式发送、已读/未读标记和移动邮件,也支持列出账号与跨账号搜索。不过存在两个实质性偏差。第一,描述中明确提到“按关键词和截止时间生成邮件巡检摘要”,但该代码块没有任何 summary/inspection/audit 类命令、参数或输出逻辑,只能搜索与列出邮件,不能生成摘要。第二,描述强调同一账号连续处理以避免账号交叉,代码只在 send 子命令加载草稿时通过 ACCOUNT_HEADER 防止用不同账号发送;而 read、reply-draft、forward 之间并没有统一的状态跟踪或强制继承机制,仍主要依赖显式传入 --account。因此描述比实际实现更强,属于能力声明与实现不完全一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

声明描述的是一个较完整的多账户邮箱代理,覆盖读取、搜索、附件处理、回复/转发/发送、邮件状态修改、移动邮件和巡检摘要等广泛操作;而当前代码块主要是“邮件巡检摘要工作流”入口。它确实支持多账户读取、默认/指定/全账号巡检、按账号保持转发时使用原账号、可选立即发送或保存转发草稿,这些与描述部分一致。但从该代码本身看,不包含列出账号、搜索邮件、读取正文/链接/附件的独立能力、下载附件、回复草稿、回复发送、标记未读、移动邮件等多项已声明核心能力。相反,代码还包含发送通知到通道、输出分析文件、保存 raw .eml、清理历史文件等描述中未明确强调的行为。虽然其中一部分能力可能存在于其他模块,但就“所提供代码块实际做什么”而言,其主用途明显偏向邮件摘要巡检而非完整通用邮箱代理,因此应判定为描述与代码行为存在实质性不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

该代码块的实际功能范围明显窄于声明。它是单一的 IMAP 读取/抓取工具,而不是完整的“多账户 IMAP/SMTP 邮箱代理”。已实现的能力包括:基于配置选择账号、连接 IMAP、读取指定邮箱近若干小时内的邮件、提取正文/链接/附件文件名、可选保存原始邮件、以及通过是否只读选择可能将邮件标记为已读。未见任何 SMTP 发送、草稿、转发、移动、未读恢复、关键词搜索、截止时间分析、巡检摘要生成等实现。多账户方面也仅限于选择一个账号读取,并无声明中所述的跨账号操作与后续同账号处理流程。因此描述与代码行为存在实质性不匹配。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

load_python_config() imports and executes a Python file from a path influenced by the --config argument using spec.loader.exec_module(module). That gives arbitrary code execution to anyone who can supply or replace the config file, which is unrelated to email analysis and especially risky in an agent skill that may process external inputs or run with mailbox access.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/first-run-guide.md (reported line 85)May include surrounding context.

md
parser.add_argument("--imap-port", type=int, default=_IMAP_SSL_PORT)
    parser.add_argument("--smtp-host", default="")
    parser.add_argument("--smtp-port", type=int, default=0)
    parser.add_argument("--skip-test", action="store_true", help="跳过连接验证")
    parser.add_argument("--force", action="store_true", help="强制覆盖已有配置")
    args = parser.parse_args()

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/init_config.py (reported line 459)May include surrounding context.

python
parser.add_argument("--imap-port", type=int, default=_IMAP_SSL_PORT)
    parser.add_argument("--smtp-host", default="")
    parser.add_argument("--smtp-port", type=int, default=0)
    parser.add_argument("--skip-test", action="store_true", help="跳过连接验证")
    parser.add_argument("--force", action="store_true", help="强制覆盖已有配置")
    args = parser.parse_args()

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

move_message implements IMAP COPY followed by setting \Deleted and expunge, which permanently removes the original message from the source mailbox. In a multi-account mail agent with cross-account operations, invoking this without a strong confirmation or safer two-phase workflow can cause irreversible data loss or mailbox tampering if the agent is prompted incorrectly or abused.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises and instructs use of shell, file, environment, and network-capable scripts, but does not declare any explicit tool scope or permission boundaries. In a mail-handling skill, those capabilities enable access to local secrets, mailbox credentials, attachment files, and outbound network actions; without scoped declarations, an agent may invoke broader operations than reviewers or users expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger phrases are very broad and likely to match ordinary email-related user requests, causing the skill to activate in contexts where the user may not intend this specific local mail agent to handle the task. Because the skill has access to shell, files, network, and potentially multiple accounts, overbroad routing increases the chance of unintended mailbox access, attachment handling, or outbound email actions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The entire guide is written only in Chinese and does not indicate that language selection is optional or configurable. Per the policy criteria, forcing a specific language or locale without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file contains user-facing operational instructions only in Chinese, and there is no indication that the skill supports other languages or that Chinese is a required locale. That can violate a language/locale policy when users are not given an explicit language choice or opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The entire guide is written in Chinese and provides no indication that users may choose another language or that the skill is intentionally limited to a Chinese-language or region-specific context. Under the stated policy, forcing a specific language without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document begins with '输出格式' and states '默认输出 Markdown', while the entire prescribed output format is in Chinese, indicating the skill expects responses in a specific language. This is a natural-language policy concern because it forces a locale/language choice without offering the user an option or explaining a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide explicitly recommends passing a sensitive client value via a temporary file under /tmp, which can expose secrets through weak file permissions, predictable paths, residual data on disk, or access by other local users/processes. In a multi-account mail agent, those credentials may grant access to one or more mailboxes, making secret leakage more consequential than a generic config issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python file hard-codes Chinese keywords, Chinese todo text, and Chinese markdown output headings, which effectively constrains the skill to a specific language/locale. There is no user-facing option to choose output language or opt in to this locale behavior, so it creates a natural-language policy concern under the language/locale rule.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file’s natural-language comments are entirely in Chinese and describe the skill behavior without offering any language choice or documenting a justified region-specific constraint. Under the policy, forcing a specific language without opt-in is a natural-language policy violation applicable to all file types.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script description says it is for viewing and quickly forwarding mail assistant outputs, but the implementation supports immediate SMTP transmission with --send. In a mail-agent skill context handling potentially sensitive multi-account email, this mismatch can cause operators to expose message contents and attachments externally when they may expect draft-only behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

When --send is used, the script transmits the selected email body and may attach the original raw message as original.eml, which can include sensitive content and metadata. In this multi-account mail-agent context, forwarding mail is expected functionality, but the lack of an explicit warning or confirmation before external transmission increases the chance of accidental data leakage.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The module docstring says "Initialize single-account mail assistant configuration," which directly conflicts with the implemented behavior. The script loads existing accounts, adds or overwrites accounts, supports --account and --set-default, and its help/output repeatedly describes configuring multiple mailbox accounts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file contains extensive natural-language strings that require Chinese comprehension, including credential-handling guidance and later CLI help/output. That effectively forces a specific language/locale for all users without offering an alternative or opt-in, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.