Back to skill

Security audit

Email IMAP/SMTP

Security checks for vulnerabilities and agentic risk

Overview

This email skill is mostly coherent, but it handles mailbox credentials and OAuth tokens in ways that can expose secrets if used carelessly.

Review before installing. Use environment variables or another protected secret mechanism instead of putting passwords or tokens in commands, avoid `--show-token`, only use known HTTPS OAuth token endpoints, and preview recipients, body, and attachments before sending mail.

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

Error
Location
scripts/email_ops.py:235
Finding
OAuth Credentials Can Be Transmitted to a Plaintext Token Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/email_ops.py`, lines 235-310 **Vulnerability Type**: Unencrypted transmission of sensitive OAuth credentials **Risk Level**: High ### Complete Code Snippet ```python token_endpoint = args.token_endpoint or os.getenv("EMAIL_TOKEN_ENDPOINT") or oauth_defaults.get("token_endpoint") client_id = args.client_id or os.getenv("EMAIL_CLIENT_ID") client_secret = args.client_secret or os.getenv("EMAIL_CLIENT_SECRET") scope = args.scope or os.getenv("EMAIL_SCOPE") or oauth_defaults.get("scope") ``` ```python def refresh_access_token(config: MailConfig) -> dict: if not config.refresh_token: raise ValueError("Missing refresh token.") if not config.token_endpoint: raise ValueError("Missing token endpoint. Set --token-endpoint or EMAIL_TOKEN_ENDPOINT.") if not config.client_id: raise ValueError("Missing client id. Set --client-id or EMAIL_CLIENT_ID.") payload = { "grant_type": "refresh_token", "refresh_token": config.refresh_token, "client_id": config.client_id, } if config.client_secret: payload["client_secret"] = config.client_secret if config.scope: payload["scope"] = config.scope data = urllib.parse.urlencode(payload).encode("utf-8") request = urllib.request.Request( config.token_endpoint, data=data, method="POST", headers={"Content-Type": "application/x-www-form-urlencoded"}, ) try: with urllib.request.urlopen(request, timeout=30) as response: body = response.read().decode("utf-8") ``` ### Technical Analysis The OAuth token endpoint can be supplied through `--token-endpoint` or `EMAIL_TOKEN_ENDPOINT`, but its URL scheme and destination are not validated before the request is made. The form-encoded POST body contains a reusable refresh token, client ID, optional client secret, and requested scope. If the endpoint uses `http://`, these credentials ...[truncated 1503 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the configured endpoint with `urllib.parse.urlparse()` and require the `https` scheme. 2. Reject URLs containing embedded usernames or passwords. 3. Permit plaintext HTTP only for explicitly enabled loopback development endpoints such as `127.0.0.1` or `localhost`. 4. Disable redirects for token requests or validate every redirect target before forwarding credential-bearing requests. 5. Consider restricting token endpoints to known provider endpoints unless an explicit custom-endpoint mode is enabled. 6. Avoid including provider response bodies in errors because they may contain sensitive token-related data. 7. Add tests confirming that plaintext, malformed, credential-bearing, and unsafe redirect URLs are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/email_ops.py:617
Finding
Mailbox Credentials and OAuth Secrets Can Be Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/email_ops.py`, lines 617-622 **Vulnerability Type**: Sensitive information exposure through process arguments and shell history **Risk Level**: Medium ### Complete Code Snippet ```python parser.add_argument("--password", help="Mailbox password or app password") parser.add_argument("--access-token", help="OAuth2 access token") parser.add_argument("--refresh-token", help="OAuth2 refresh token") parser.add_argument("--token-endpoint", help="OAuth2 token endpoint for refresh") parser.add_argument("--client-id", help="OAuth2 client id") parser.add_argument("--client-secret", help="OAuth2 client secret") ``` The documentation also demonstrates passing secrets directly on the command line: ```bash python scripts/email_ops.py token --provider outlook --email you@outlook.com --auth-mode oauth2 --refresh-token "<REFRESH_TOKEN>" --client-id "<CLIENT_ID>" --client-secret "<CLIENT_SECRET>" ``` ### Technical Analysis The command-line interface accepts mailbox passwords, access tokens, refresh tokens, and OAuth client secrets directly as arguments. Command-line arguments can be retained in shell history, captured by terminal or agent transcripts, collected by process-auditing systems, and, depending on operating-system configuration, observed through process inspection. Although the Skill recommends environment variables, its documented token-refresh example explicitly encourages command-line secret submission. Environment variables also require careful handling, but they normally avoid shell-history and command-line process-list exposure. The ability to provide authentication material is necessary for the declared mailbox operations. Exposing reusable secrets through ordinary command-line arguments is not necessary and increases local credential exposure. ### Attack Path 1. A user follows the documented example or passes a password, token, or client secret through a CLI option. 2. The shell records the ...[truncated 1081 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove or deprecate CLI options that accept passwords, access tokens, refresh tokens, and client secrets. 2. Read interactive passwords through `getpass.getpass()` so they are not echoed or included in process arguments. 3. Support protected secret files, file descriptors, standard input, or an operating-system credential store. 4. If environment variables remain supported, document their local exposure considerations and avoid printing them. 5. Replace documentation examples containing secret CLI arguments with protected environment-variable or interactive-input examples. 6. Emit a warning when a sensitive command-line option is used during a transition period. 7. Ensure application errors, debug logs, and generated reports redact all credential values. ]]>
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (17)

Credential Access

High
Category
Privilege Escalation
Content
- Email address (login username)
- Authentication:
  - Password mode: app password / authorization code
  - OAuth2 mode: access token, or refresh token + client info
- IMAP host/port
- SMTP host/port
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Email address (login username)
- Authentication:
  - Password mode: app password / authorization code
  - OAuth2 mode: access token, or refresh token + client info
- IMAP host/port
- SMTP host/port
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
- Email address (login username)
- Authentication:
  - Password mode: app password / authorization code
  - OAuth2 mode: access token, or refresh token + client info
- IMAP host/port
- SMTP host/port
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
parser.add_argument("--email", help="Mailbox login email")
    parser.add_argument("--auth-mode", choices=["auto", "password", "oauth2"], default="auto", help="Authentication mode")
    parser.add_argument("--password", help="Mailbox password or app password")
    parser.add_argument("--access-token", help="OAuth2 access token")
    parser.add_argument("--refresh-token", help="OAuth2 refresh token")
    parser.add_argument("--token-endpoint", help="OAuth2 token endpoint for refresh")
    parser.add_argument("--client-id", help="OAuth2 client id")
Confidence
93% confidence
Finding
The CLI accepts sensitive secrets such as passwords, access tokens, refresh tokens, and client secrets directly as command-line arguments. On many systems, command-line arguments are visible to other local users via process listings, shell history, job control logs, or audit tooling, which can expose mailbox credentials and OAuth tokens.

Credential Access

High
Category
Privilege Escalation
Content
p_send.add_argument("--html-file", help="Path to HTML body file")
    p_send.add_argument("--attach", action="append", help="Attachment path (repeatable)")

    p_token = subparsers.add_parser("token", help="Resolve OAuth2 access token")
    p_token.add_argument("--show-token", action="store_true", help="Print full token instead of masked output")

    p_auth = subparsers.add_parser("auth-url", help="Build OAuth2 authorization URL")
Confidence
91% confidence
Finding
The token subcommand can print the resolved OAuth access token in full when --show-token is used, creating a straightforward secret exposure path to stdout, logs, terminal scrollback, and calling agent transcripts. In an agent skill context, this is more dangerous because tool output is often captured and persisted automatically.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill invokes local scripts that rely on environment variables, file access, and outbound network connectivity, but the manifest declares no explicit tool scope or permissions boundary. This creates an authorization gap where an agent may use broader capabilities than reviewers or users expect, increasing the chance of unintended credential access, file reads, or network operations.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"smtp_port": 465,
        "smtp_ssl": True,
        "oauth": {
            "auth_endpoint": "https://api.login.yahoo.com/oauth2/request_auth",
            "token_endpoint": "https://api.login.yahoo.com/oauth2/get_token",
            "scope": "openid mail-r mail-w",
        },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The token refresh flow transmits refresh tokens and possibly client secrets to a remote token endpoint, which is a sensitive network operation. Although this is standard OAuth behavior, the code provides no warning, confirmation, or nearby disclosure about sending credential material to external services.

Missing User Warnings

Medium
Confidence
80% confidence
Finding
The list and read commands connect to IMAP and retrieve email headers, bodies, and attachment names, which are typically sensitive user data. The code contains functional help text but no explicit warning or disclosure that it accesses and outputs private mailbox contents.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code performs an external SMTP send of user-provided body content and attachment files, which can transmit sensitive data off-system. In this file there is no confirmation prompt, visible user disclosure at send time, or warning-oriented comment/docstring around the operation.

Static analysis

No suspicious patterns detected.