Back to skill

Security audit

OpenCloutlook

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Outlook mail and calendar purpose, but it needs review because it handles persistent Microsoft tokens, can print an access token, and includes an LLM example that can perform mail or calendar changes without explicit user confirmation.

Review before installing. Use this only on a trusted machine, protect ~/.openclaw/msgraph-tokens.json, avoid running the token-printing command, and do not use the LLM integration example for automatic moves or event creation unless you add explicit review and approval before every action. Consider removing unused User.Read and using narrower read-only scopes if you do not need mail or calendar mutation.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (5)

other

Warning
Location
examples/README.md:58
Finding

Mailbox Metadata May Be Disclosed to Third-Party LLM Providers

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
examples/llm_integration.py:164
Finding

Untrusted Mailbox Content Can Influence Unconfirmed Graph Mutations

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:278
Finding

Privileged Microsoft Graph Access Token Can Be Printed to Standard Output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:86
Finding

OAuth Tokens Are Written Before Restrictive File Permissions Are Applied

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Note
Location
config.example.ini:4
Finding

Default OAuth Configuration Requests an Unused User Profile Scope

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (64)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code aligns strongly with the mail portion of the description: it accesses Outlook mail folders and messages through Microsoft Graph, supports reading inbox/folder contents, moving messages, and listing folders. However, the declared purpose also states calendar capabilities such as listing events and creating events, and no calendar-related behavior appears in this code chunk. That is a material description-to-code gap for this specific chunk. Additionally, the code supports email search and marks messages as read when opened; these are extra mail behaviors not explicitly mentioned, though they are adjacent to the declared mail-management purpose. Overall, this chunk is narrower than the declared skill description, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Yes, this is a mismatch based on the provided code chunk. The declared description promises substantive Outlook inbox and calendar management via Microsoft Graph, but the actual code shown is only an init.py file for tests containing a docstring. There is no functional behavior to support the declared capabilities. While this may be only a partial repository fragment, evaluating the supplied chunk alone, its actual behavior does not match the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description says the skill reads/manages Outlook email and calendar via Microsoft Graph API. However, this code chunk is focused on authentication infrastructure tests, not mailbox or calendar functionality. While Microsoft login/token handling could support a Graph-based Outlook skill, the actual code shown does not perform the declared primary functions such as reading messages, moving emails, listing events, or creating events. Therefore the supplied code materially differs from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The code shown is specifically tests/test_cal.py and focuses on calendar functionality: cmd_list, cmd_get, cmd_create, cmd_delete, and cmd_calendars. These imply actual capabilities to list events, get event details, create events, delete events, and list calendars. The declared description includes calendar listing and creation, so those parts are aligned. However, deletion of calendar events is a substantive capability not mentioned in the description. Listing calendars is also an additional calendar-management capability not explicitly described, though it is related. More importantly, the declared description strongly covers Outlook email management (read/manage inbox, folders, move messages), but this supplied code chunk contains no evidence of any email-related behavior. Because the evaluation is against the supplied chunk, the description overstates email functionality relative to the observed implementation and omits event deletion. Therefore this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code shown is only tests, but those tests clearly indicate the implemented behavior of the related mail module. That behavior aligns strongly with the email portion of the description: inbox access, message reading, marking as read, moving messages, and folder listing through Microsoft Graph. However, the declared purpose also claims Outlook calendar support (listing and creating calendar events), and nothing in this code chunk relates to calendar resources or calendar commands. Additionally, the code tests message search, which is an undeclared mail capability, though it is adjacent to the stated purpose and less material than the missing calendar functionality. Because a significant declared capability—calendar management—is not represented by the supplied code chunk, this is a description/behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This is a clear description-behavior mismatch. The declared purpose describes a fully functional Outlook/Microsoft 365 skill that interacts with user email and calendar through Microsoft Graph API. However, the provided code chunk is a test module (tests/test_utils.py) that validates helper utilities such as format_datetime, parse_local_datetime, and strip_html. While some tests mention Graph API-compatible datetime structure and email HTML cleanup, these are merely support utilities and not the claimed primary behavior. There is no evidence here of message retrieval, folder access, moving emails, listing events, creating events, authentication, Graph API requests, or access to Outlook resources. Therefore the supplied code does not accurately represent the declared skill behavior.

Content

No source excerpt is available for this finding.

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 · references/SETUP.md (reported line 220)May include surrounding context.

md
### Q: How often do tokens refresh?

**A:** Access tokens last ~1 hour. When expired, the script automatically exchanges the refresh token for a new one. The refresh token lasts ~90 days.

### Q: What happens after 90 days?

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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/SETUP.md (reported line 252)May include surrounding context.

bash
# Remove local token
rm ~/.openclaw/msgraph-tokens.json

# (Optional) Revoke in Azure Portal:
# 1. Go to Account settings → Security & privacy → Apps & services

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 · references/SETUP.md (reported line 294)May include surrounding context.

md
**A:**

- **Access token**: ~1 hour (auto-refreshes)
- **Refresh token**: ~90 days (auto-refreshes)
- **Skill remembers**: You don't need to log in again for 90 days

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 · references/api.md (reported line 19)May include surrounding context.

md
Stored at `~/.openclaw/msgraph-tokens.json` (mode 0600). Contains:
- `access_token` — Bearer token for API calls
- `refresh_token` — Long-lived token for renewal
- `expires_at` — Unix timestamp of access token expiry
- `expires_in` — Seconds until expiry (from last refresh)

## Key Endpoints

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 · README.md (reported line 119)May include surrounding context.

md
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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 · README.md (reported line 120)May include surrounding context.

md
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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 · scripts/auth.py (reported line 10)May include surrounding context.

python
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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 · scripts/auth.py (reported line 131)May include surrounding context.

python
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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 · scripts/auth.py (reported line 134)May include surrounding context.

python
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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 · scripts/auth.py (reported line 259)May include surrounding context.

python
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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_auth.py (reported line 404)May include surrounding context.

python
python auth.py login    - Initiate PKCE auth flow (opens browser)
  python auth.py status   - Show current auth status
  python auth.py refresh  - Force token refresh
  python auth.py token    - Print current access token (for scripting)
"""

import os

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 · scripts/auth.py (reported line 257)May include surrounding context.

python
remaining = expires_at - time.time()
    if remaining > 0:
        print(f"Status: authenticated")
        print(f"Access token expires in: {int(remaining)}s")
    else:
        print("Status: access token expired (will auto-refresh on next use)")
    has_refresh = bool(tokens.get("refresh_token"))

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation explicitly includes a command to print the current access token without warning that it is a bearer credential. Exposing an access token in terminal output, logs, transcripts, or screenshots can let anyone with access to that output reuse the token to access the user's Microsoft data until expiry, making this a real credential exposure risk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

Providing a command that prints the current access token is a direct credential-access mechanism. Because Microsoft Graph access tokens are bearer tokens, anyone who obtains the printed value can potentially read or modify the user's mail and calendar data for the token's lifetime; the presence of persistent token storage in this skill increases the sensitivity of credential handling overall.

Content

Scanner excerpt · skill.md (reported line 24)May include surrounding context.

python scripts/auth.py status # Check if authenticated python scripts/auth.py login # Full PKCE login (opens browser — interactive, needs user) python scripts/auth.py refresh # Force token refresh python scripts/auth.py token # Print current access token

text

**First-time setup:** Run `auth.py login`. A browser window opens for Microsoft login. After login, tokens are stored and auto-refreshed on future calls.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · CONTRIBUTING.md (reported line 64)May include surrounding context.

Making Changes

  1. Create a feature branch:

    bash
    git checkout -b feature/my-feature
    

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documentation states that OAuth tokens are stored under ~/.openclaw/ but gives no warning about the sensitivity of those credentials or expectations for filesystem protections. For a skill that accesses Outlook mail and calendar data, stolen refresh/access tokens could enable unauthorized access to highly sensitive user communications and scheduling information.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest says the skill can list and create Outlook calendar events, but this documentation states the code supports event deletion via cmd_delete(). Deleting calendar events is a materially broader management action than the manifest advertises, creating a description-to-behavior mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly states that OAuth tokens are stored locally but does not warn that refresh tokens and access tokens are sensitive credentials that can grant ongoing access to a user's mailbox and calendar if the host is compromised or the file permissions are weak. In the context of an email/calendar skill, this omission matters because the stored token can enable persistent access to private communications and account data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
79% confidence
Finding

The documented use of the offline_access scope and local token persistence enables long-lived sessions through refresh tokens. In an Outlook/Calendar skill, that increases the risk that a stolen local token file can be used to maintain access to sensitive email and calendar data even after the original access token expires.

Content

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

[msgraph] CLIENT_ID = your-client-id-here tenant = consumers scopes = Mail.ReadWrite Calendars.ReadWrite offline_access User.Read redirect_port = 8765

text

Static analysis

No suspicious patterns detected.