Back to skill

Security audit

Outlook

Security checks for vulnerabilities and agentic risk

Overview

This Outlook skill mostly does what it says, but it asks for durable read/write/send access to mail and calendar data and has under-scoped handling of tokens, destructive actions, and attachment downloads.

Install only if you are comfortable granting this skill read/write/send access to your Outlook mail and read/write access to your calendar with refresh-token persistence. Avoid running the displayed curl-to-sudo-bash Azure CLI installer, do not use the token-printing command in logged agent sessions, confirm any send/delete/bulk/folder/calendar action yourself, and treat downloaded attachments as able to overwrite local files unless you choose a safe empty directory.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/outlook-setup.sh:29
Finding

Privileged Execution of an Unverified Remote Installation Script

Content
View full analysis
/dev/null; then echo -e "${RED}Error: Azure CLI not installed${NC}" echo "Install with: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash" exit 1 fi ``` ### Technical Analysis The setup script instructs the user or calling Agent to retrieve a script from a mutable URL and pipe it directly into a root shell: ```bash curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash ``` This pattern combines remote retrieval and privileged execution without: - Pinning the retrieved content to a specific version. - Validating a cryptographic checksum. - Verifying a detached signature. - Allowing the user to inspect the downloaded payload before execution. - Separating download and privileged installation operations. The URL is hosted under a Microsoft-controlled domain, which reduces but does not eliminate the supply-chain risk. The effective code executed by this command can change after the Skill has been reviewed. The Skill does not execute this command automatically, but displaying it as the prescribed installation procedure can cause a user or Agent to execute it. ### Attack Path 1. The user runs `scripts/outlook-setup.sh` on a system without Azure CLI. 2. The script displays the network-to-shell installation command. 3. The user or an automated Agent executes the displayed command. 4. `curl` follows redirects and retrieves the current response from the remote endpoint. 5. The response is passed directly to `sudo bash`. 6. If the endpoint, redirect chain, delivery infrastructure, or retrieved content is compromised or unexpectedly modified, arbitrary commands execute with root privileges. ### Impact Assessment Successful exploitation provides arbitrary root-level code execution. A malicious remote payload could: - Rea ...[truncated 442 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/outlook-mail.sh:383
Finding

Arbitrary File Overwrite Through Attachment Download Paths

Content
View full analysis
[output-path] MSG_ID="$2" ATT_NAME="$3" OUTPUT="${4:-.}" if [ -z "$ATT_NAME" ]; then echo "Usage: outlook-mail.sh download [output-path]" echo "Use 'attachments ' to see available attachments" exit 1 fi FULL_ID=$(curl -s "$API/messages?\$top=100&\$select=id" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq -r ".value[] | select(.id | endswith(\"$MSG_ID\")) | .id" | head -1) if [ -z "$FULL_ID" ]; then echo "Message not found" exit 1 fi # Get attachment by name ATT_DATA=$(curl -s "$API/messages/$FULL_ID/attachments" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq -r ".value[] | select(.name == \"$ATT_NAME\")") if [ -z "$ATT_DATA" ]; then echo "Attachment not found: $ATT_NAME" echo "Available attachments:" curl -s "$API/messages/$FULL_ID/attachments" -H "Authorization: Bearer $ACCESS_TOKEN" | jq -r '.value[].name' exit 1 fi # Get content and decode ATT_ID=$(echo "$ATT_DATA" | jq -r '.id') CONTENT=$(curl -s "$API/messages/$FULL_ID/attachments/$ATT_ID" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq -r '.contentBytes') OUTPUT_FILE="$OUTPUT/$ATT_NAME" echo "$CONTENT" | base64 -d > "$OUTPUT_FILE" ``` ### Technical Analysis The script constructs the destination path directly from the caller-controlled output path and attachment name: ```bash OUTPUT_FILE="$OUTPUT/$ATT_NAME" ``` It does not reject: - Absolute or traversal-based paths. - `..` path components. - Path separators in attachment names. - Symbolic-link destinations. - Existing files. - Destin ...[truncated 2004 chars]
Remediation
View remediation
` redirection. 7. Set a restrictive `umask`, such as `077`, before creating downloaded files. 8. Obtain the attachment name safely with: ```bash jq -r --arg name "$ATT_NAME" '.value[] | select(.name == $name)' ``` 9. Require explicit confirmation before replacing any existing file. 10. Validate the attachment type and size before holding or decoding it. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/outlook-mail.sh:45
Finding

Parser Injection and Request Manipulation Through Unsafe Argument Interpolation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/outlook-token.sh:39
Finding

OAuth Bearer Token Exposed Through Standard Output

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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (76)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk is specifically an Outlook calendar shell script using Microsoft Graph /me/calendar, /me/calendarView, and /me/calendars endpoints. It supports viewing, creating, updating, and deleting calendar events plus availability checks. The declared description says the skill can read, search, and manage Outlook emails and calendar, and suggests use for inbox/mail requests. That overstates the implemented behavior because no email endpoints or email-related actions appear in this code. While the calendar/scheduling portion matches, the email portion is materially unsupported, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code clearly operates on Outlook email through Microsoft Graph and supports substantial mailbox management. However, the declared description explicitly includes calendar management and scheduling, while the supplied code contains no calendar/event endpoints or functionality at all. That is a material description-to-behavior mismatch. Additionally, the script can download attachments to the local filesystem, which is a notable capability not mentioned in the description. It also sends/replies/forwards emails and drafts messages; these may fall under broad 'manage Outlook emails,' so they are a weaker mismatch than the missing calendar support. The primary mismatch is that the description overstates coverage by claiming calendar/scheduling features that are absent.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

A command that prints the access token to stdout is dangerous because logs, transcripts, shell history, or downstream tools may capture the token. A leaked bearer token can be used immediately to access or manipulate the user's email and calendar through Microsoft Graph.

Content

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

bash
./scripts/outlook-token.sh refresh  # Refresh expired token
./scripts/outlook-token.sh test     # Test connection
./scripts/outlook-token.sh get      # Print access token

Reading Emails

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The documentation identifies a local file containing OAuth access and refresh tokens and another containing client credentials, creating a clear credential target for any component with file access. In an agent environment, exposing where long-lived tokens are stored materially increases the risk of account takeover and persistent mailbox/calendar access.

Content

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

md
## Files

- `~/.outlook-mcp/config.json` - Client ID and secret
- `~/.outlook-mcp/credentials.json` - OAuth tokens (access + refresh)

## Permissions

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The guide instructs users to write OAuth tokens returned by the token endpoint directly to ~/.outlook-mcp/credentials.json. For an Outlook skill with Mail.ReadWrite, Mail.Send, and Calendars.ReadWrite scopes plus offline_access, compromise of this file can provide durable access to private mailboxes and calendar data and enable unauthorized actions as the user.

Content

Scanner excerpt · references/setup.md (reported line 92)May include surrounding context.

curl -s -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token"
-H "Content-Type: application/x-www-form-urlencoded"
-d "client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&code=$AUTH_CODE&redirect_uri=http://localhost&grant_type=authorization_code&scope=https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send https://graph.microsoft.com/Calendars.ReadWrite offline_access" \

~/.outlook-mcp/credentials.json

chmod 600 ~/.outlook-mcp/credentials.json

text

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

Although chmod 600 is a good mitigation, this section still confirms the existence and storage location of a live credential file containing Outlook OAuth tokens. Because the skill grants read/write email and calendar access and includes offline_access, theft of this file could enable persistent account access until revoked or expired/rotated.

Content

Scanner excerpt · references/setup.md (reported line 94)May include surrounding context.

-d "client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&code=$AUTH_CODE&redirect_uri=http://localhost&grant_type=authorization_code&scope=https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/Mail.Send https://graph.microsoft.com/Calendars.ReadWrite offline_access" \

~/.outlook-mcp/credentials.json

chmod 600 ~/.outlook-mcp/credentials.json

text

## Step 7: Verify Setup

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The verification step reads the access token from disk into a shell variable and uses it in a command, normalizing routine handling of bearer tokens in plaintext shell workflows. In this context, bearer tokens authorize mailbox access directly, and shell-based handling can increase accidental exposure via process inspection, terminal history, debugging, or copy/paste mistakes.

Content

Scanner excerpt · references/setup.md (reported line 100)May include surrounding context.

Step 7: Verify Setup

bash
ACCESS_TOKEN=$(jq -r '.access_token' ~/.outlook-mcp/credentials.json)

curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/inbox" \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq '{total: .totalItemCount, unread: .unreadItemCount}'

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

md
- Make sure you click "Accept" on the consent screen

### "Token expired"
- Access tokens last ~1 hour
- Run `./scripts/outlook-token.sh refresh` to get a new one

### Work/School Account Issues

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

md
- Make sure you click "Accept" on the consent screen

### "Token expired"
- Access tokens last ~1 hour
- Run `./scripts/outlook-token.sh refresh` to get a new one

### Work/School Account Issues

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 122)May include surrounding context.

md
- Make sure you click "Accept" on the consent screen

### "Token expired"
- Access tokens last ~1 hour
- Run `./scripts/outlook-token.sh refresh` to get a new one

### Work/School Account Issues

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/outlook-calendar.sh (reported line 6)May include surrounding context.

sh
# Usage: outlook-mail.sh <command> [args]

CONFIG_DIR="$HOME/.outlook-mcp"
CREDS_FILE="$CONFIG_DIR/credentials.json"

# Load token
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

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/outlook-mail.sh (reported line 6)May include surrounding context.

sh
# Usage: outlook-mail.sh <command> [args]

CONFIG_DIR="$HOME/.outlook-mcp"
CREDS_FILE="$CONFIG_DIR/credentials.json"

# Load token
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

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/outlook-token.sh (reported line 7)May include surrounding context.

sh
# Usage: outlook-mail.sh <command> [args]

CONFIG_DIR="$HOME/.outlook-mcp"
CREDS_FILE="$CONFIG_DIR/credentials.json"

# Load token
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

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/outlook-calendar.sh (reported line 12)May include surrounding context.

sh
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
    echo "Error: No access token. Run setup first."
    exit 1
fi

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/outlook-mail.sh (reported line 12)May include surrounding context.

sh
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
    echo "Error: No access token. Run setup first."
    exit 1
fi

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/outlook-token.sh (reported line 61)May include surrounding context.

sh
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
    echo "Error: No access token. Run setup first."
    exit 1
fi

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/outlook-token.sh (reported line 62)May include surrounding context.

sh
ACCESS_TOKEN=$(jq -r '.access_token' "$CREDS_FILE" 2>/dev/null)

if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
    echo "Error: No access token. Run setup first."
    exit 1
fi

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The script is explicitly built to create and persist a credentials.json file containing OAuth tokens, which are sensitive bearer credentials granting access to Outlook and calendar data. In the context of broad Graph scopes and offline access, local credential storage materially raises the risk of account compromise if the host is breached or files are leaked.

Content

Scanner excerpt · scripts/outlook-setup.sh (reported line 9)May include surrounding context.

sh
CONFIG_DIR="$HOME/.outlook-mcp"
CONFIG_FILE="$CONFIG_DIR/config.json"
CREDS_FILE="$CONFIG_DIR/credentials.json"

APP_NAME="Clawdbot-Outlook"
REDIRECT_URI="http://localhost"

External Script Fetching

High
Category
Supply Chain
Confidence
97% confidence
Finding

The script recommends installing Azure CLI with a curl-to-sudo-bash one-liner, a well-known unsafe pattern that executes remotely fetched content with elevated privileges. Although it is printed rather than auto-executed, embedding this guidance in a setup flow normalizes risky behavior and could lead users to run arbitrary code as root if the source or transport is ever compromised.

Content

Scanner excerpt · scripts/outlook-setup.sh (reported line 29)May include surrounding context.

sh
check_prereqs() {
    if ! command -v az &> /dev/null; then
        echo -e "${RED}Error: Azure CLI not installed${NC}"
        echo "Install with: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash"
        exit 1
    fi

Chaining Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

The suggested install command chains a network fetch directly into privileged shell execution, which is exactly the kind of command chaining that can turn a network or source compromise into immediate root code execution. Even as displayed guidance, it is dangerous because users commonly copy-paste setup commands verbatim.

Content

Scanner excerpt · scripts/outlook-setup.sh (reported line 29)May include surrounding context.

sh
check_prereqs() {
    if ! command -v az &> /dev/null; then
        echo -e "${RED}Error: Azure CLI not installed${NC}"
        echo "Install with: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash"
        exit 1
    fi

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises and relies on shell scripts but does not declare any explicit tool scope such as allowed shell access or command boundaries. In an agent environment, undeclared shell capability increases the chance of overbroad execution, unexpected side effects, and abuse through natural-language triggering of local command execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The description includes broad trigger phrases like emails, inbox, Outlook, calendar, and scheduling, which can cause the skill to activate on common user requests. In an autonomous agent setting, overly broad routing increases the risk of invoking privacy-sensitive mail/calendar actions when the user did not intend to grant that level of access.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The setup flow creates a persistent app registration and stores refresh-capable credentials locally, enabling long-term access beyond the immediate session. If those persisted artifacts are stolen or misused, an attacker can maintain ongoing mailbox and calendar access without repeatedly prompting the user.

Content

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

md
The setup script will:
1. Log you into Azure (device code flow)
2. Create an App Registration automatically
3. Configure API permissions (Mail.ReadWrite, Mail.Send, Calendars.ReadWrite)
4. Guide you through authorization
5. Save credentials to `~/.outlook-mcp/`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill documents destructive and privacy-sensitive operations such as delete, archive, move, send, and reply, but provides no confirmation or user-consent safeguards. In a conversational agent, this can lead to accidental data loss, unauthorized message transmission, or privacy breaches from a misunderstood prompt.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/setup.md (reported line 9)May include surrounding context.

md
- Microsoft account (Outlook.com, Hotmail, Live, or Microsoft 365)
- Access to [Azure Portal](https://portal.azure.com)
- `jq` installed (`sudo apt install jq`)

## Step 1: Create Azure App Registration

Static analysis

No suspicious patterns detected.