other
- Location
examples/README.md:58- Finding
Mailbox Metadata May Be Disclosed to Third-Party LLM Providers
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
examples/README.md:58Mailbox Metadata May Be Disclosed to Third-Party LLM Providers
examples/llm_integration.py:164Untrusted Mailbox Content Can Influence Unconfirmed Graph Mutations
scripts/auth.py:278Privileged Microsoft Graph Access Token Can Be Printed to Standard Output
scripts/auth.py:86OAuth Tokens Are Written Before Restrictive File Permissions Are Applied
config.example.ini:4Default OAuth Configuration Requests an Unused User Profile Scope
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.
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.
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.
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.
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.
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.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
### 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 parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
# Remove local token
rm ~/.openclaw/msgraph-tokens.json
# (Optional) Revoke in Azure Portal:
# 1. Go to Account settings → Security & privacy → Apps & services
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
**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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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"))
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.
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.
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
**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.
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.
Create a feature branch:
git checkout -b feature/my-feature
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.
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.
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.
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.
[msgraph] CLIENT_ID = your-client-id-here tenant = consumers scopes = Mail.ReadWrite Calendars.ReadWrite offline_access User.Read redirect_port = 8765
No suspicious patterns detected.