Back to skill

Security audit

outlook-mcp

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed Outlook connector that can read and change mailbox data, but its high-impact abilities are aligned with its stated purpose and documented controls.

Install only if you want an agent to access personal Outlook data. Start with read_only true, use allow_categories for any writes, keep attachments_dir narrow, and avoid allow_unencrypted_token_cache unless you accept plaintext token storage on that host. For a true read-only credential, register a separate Azure app with only read scopes, because the local read_only flag is a tool guardrail rather than a Microsoft-enforced token limit.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (109)

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
90% confidence
Finding

Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Content

Scanner excerpt · README.md (reported line 52)May include surrounding context.

md
## Works With

- **[OpenClaw](https://openclaw.ai)** — native MCP support, available via [ClawHub](https://clawhub.ai/skills?q=outlook-mcp)
- **[Claude Code](https://claude.com/claude-code)** — add to `~/.claude/settings.json` under `mcpServers`
- **[Cursor](https://cursor.com)** — MCP-compatible
- **Any MCP client** — it's a standard stdio MCP server

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · RELEASING.md (reported line 158)May include surrounding context.

6c. Verify — the CLI's success message is not verification.

bash
curl -s -o /dev/null -w '%{http_code}\n' https://clawhub.ai/api/v1/skills/outlook-mcp/versions/X.Y.Z   # 200 once public
curl -s https://clawhub.ai/api/v1/skills/outlook-mcp | python3 -c "import json,sys; print(json.load(sys.stdin)['latestVersion']['version'])"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · RELEASING.md (reported line 190)May include surrounding context.

And confirm the MCP registry shows the new version as (latest):

bash
curl -s 'https://registry.modelcontextprotocol.io/v0/servers?search=mpalermiti&limit=20' | python3 -c "import json,sys; [print(s['server'].get('version'), '(latest)' if s.get('_meta',{}).get('io.modelcontextprotocol.registry/official',{}).get('isLatest') else '') for s in json.load(sys.stdin).get('servers', [])]"

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · README.md (reported line 394)May include surrounding context.

md
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · README.md (reported line 395)May include surrounding context.

md
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

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

md
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

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

md
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · src/outlook_mcp/tools/mail_attachments.py (reported line 355)May include surrounding context.

python
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · tests/test_mail_attachments.py (reported line 309)May include surrounding context.

python
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · tests/test_mail_attachments.py (reported line 320)May include surrounding context.

python
### Attachments
- `outlook_list_attachments` — List on a message
- `outlook_download_attachment` — Download and save decoded bytes into `attachments_dir`
- `outlook_send_with_attachments` — Send with files read from `attachments_dir` (auto upload session for >3MB)
- `outlook_attach_to_draft` — Add attachments to an existing draft (auto upload session for >3MB)
- `outlook_remove_draft_attachment` — Remove a single attachment from a draft

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/outlook_mcp/auth.py (reported line 202)May include surrounding context.

python
super().__init__(
            "unencrypted_token_cache",
            "Refusing to persist the token cache: this environment has no "
            "encrypted store (Linux without libsecret/gnome-keyring), so the "
            "cache would be written to disk in cleartext.",
            "Either install the system packages (apt: `gnome-keyring "
            "libsecret-1-0 python3-gi`) and re-create the venv with "

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/outlook_mcp/auth.py (reported line 204)May include surrounding context.

python
super().__init__(
            "unencrypted_token_cache",
            "Refusing to persist the token cache: this environment has no "
            "encrypted store (Linux without libsecret/gnome-keyring), so the "
            "cache would be written to disk in cleartext.",
            "Either install the system packages (apt: `gnome-keyring "
            "libsecret-1-0 python3-gi`) and re-create the venv with "

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/outlook_mcp/errors.py (reported line 142)May include surrounding context.

python
super().__init__(
            "unencrypted_token_cache",
            "Refusing to persist the token cache: this environment has no "
            "encrypted store (Linux without libsecret/gnome-keyring), so the "
            "cache would be written to disk in cleartext.",
            "Either install the system packages (apt: `gnome-keyring "
            "libsecret-1-0 python3-gi`) and re-create the venv with "

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/outlook_mcp/errors.py (reported line 144)May include surrounding context.

python
super().__init__(
            "unencrypted_token_cache",
            "Refusing to persist the token cache: this environment has no "
            "encrypted store (Linux without libsecret/gnome-keyring), so the "
            "cache would be written to disk in cleartext.",
            "Either install the system packages (apt: `gnome-keyring "
            "libsecret-1-0 python3-gi`) and re-create the venv with "

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · CHANGELOG.md (reported line 490)May include surrounding context.

md
def _bearer_token(credential: Any) -> str:
    """Mint a Graph access token from an azure-identity credential."""
    tok = credential.get_token(GRAPH_TOKEN_SCOPE)
    return tok.token

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/outlook_mcp/tools/_delta.py (reported line 58)May include surrounding context.

python
def _bearer_token(credential: Any) -> str:
    """Mint a Graph access token from an azure-identity credential."""
    tok = credential.get_token(GRAPH_TOKEN_SCOPE)
    return tok.token

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · tests/test_keychain_collision.py (reported line 72)May include surrounding context.

python
def _bearer_token(credential: Any) -> str:
    """Mint a Graph access token from an azure-identity credential."""
    tok = credential.get_token(GRAPH_TOKEN_SCOPE)
    return tok.token

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · src/outlook_mcp/tools/mail_attachments.py (reported line 394)May include surrounding context.

python
) -> dict:
    """Remove a single attachment from a draft message.

    DELETE /me/messages/{draft_id}/attachments/{attachment_id}.
    Only useful on drafts — sent messages are immutable.
    """
    check_permission(config, CATEGORY_MAIL_DRAFTS, "outlook_remove_draft_attachment")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · src/outlook_mcp/tools/todo.py (reported line 608)May include surrounding context.

python
) -> dict:
    """Delete a task from a To Do list.

    DELETE /me/todo/lists/{id}/tasks/{taskId}
    """
    check_permission(config, CATEGORY_TODO_WRITE, "outlook_delete_task")
    task_id = validate_graph_id(task_id)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · src/outlook_mcp/tools/todo.py (reported line 744)May include surrounding context.

python
) -> dict:
    """Delete a checklist item from a task.

    DELETE /me/todo/lists/{id}/tasks/{taskId}/checklistItems/{checklistItemId}
    """
    check_permission(config, CATEGORY_TODO_WRITE, "outlook_delete_checklist_item")
    task_id = validate_graph_id(task_id)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · src/outlook_mcp/tools/todo_attachments.py (reported line 13)May include surrounding context.

python
(``POST .../attachments/createUploadSession``, verified live), but its
upload URL is a ``graph.microsoft.com`` route rather than a pre-authenticated
``outlook.office.com`` one like mail's: every chunk PUT needs an
``Authorization`` header (401 "Access token is empty" without it, verified)
and a ``Content-Type`` header (400 without it, verified), plus response
checking and offset-following of ``nextExpectedRanges``. At the sizes this
tool accepts, inline is one round-trip through kiota's throttling and retry;

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · src/outlook_mcp/tools/todo_attachments.py (reported line 355)May include surrounding context.

python
) -> dict:
    """Remove an attachment from a To Do task.

    DELETE /me/todo/lists/{id}/tasks/{taskId}/attachments/{attId}
    """
    check_permission(config, CATEGORY_TODO_WRITE, "outlook_delete_task_attachment")
    task_id = validate_graph_id(task_id)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_attachment_paths.py (reported line 148)May include surrounding context.

python
def _paths_with_env(value: str | None) -> list[str]:
    env = dict(os.environ)
    if value is None:
        env.pop("OUTLOOK_MCP_CONFIG_DIR", None)
    else:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_config.py (reported line 104)May include surrounding context.

python
def _paths_with_env(value: str | None) -> list[str]:
    env = dict(os.environ)
    if value is None:
        env.pop("OUTLOOK_MCP_CONFIG_DIR", None)
    else:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_config.py (reported line 152)May include surrounding context.

python
def _paths_with_env(value: str | None) -> list[str]:
    env = dict(os.environ)
    if value is None:
        env.pop("OUTLOOK_MCP_CONFIG_DIR", None)
    else:

Static analysis

Detected: suspicious.dynamic_code_execution, suspicious.obfuscated_code

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_preflight.py:24

Potential obfuscated payload detected.

Warn
Code
suspicious.obfuscated_code
Location
tests/test_mail_attachments.py:129