Back to skill

Security audit

Outlook for Work/School 365

Security checks for vulnerabilities and agentic risk

Overview

This Outlook skill mostly does what it claims, but it asks for powerful mail/calendar access and includes unsafe credential and file-handling patterns that users should review before installing.

Install only if you are comfortable granting this skill read/write access to Outlook mail and calendar, including sending mail and deleting or moving messages. Avoid using the token 'get' command, protect or periodically remove ~/.outlook-mcp, revoke the Azure app if you stop using the skill, do not run the curl | sudo bash installer suggestion, and be cautious downloading attachments because filenames are not safely contained.

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:25
Finding

Unpinned Remote Installer Is Recommended for Root-Level Execution

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 When Azure CLI is unavailable, the setup script recommends downloading a shell script from a mutable, redirecting URL and piping it directly into `sudo bash`. The command provides no version pinning, signature verification, checksum verification, or opportunity to inspect the downloaded content before execution. Although the URL is operated by Microsoft, its effective payload can change after the Skill has been reviewed. Consequently, executing the recommended command transfers complete trust to the current response returned through the URL and its redirect chain. This behavior exceeds the privileges needed merely to report a missing prerequisite: the Skill itself does not need to cause arbitrary remotely supplied shell content to run as root. ### Attack Path 1. A user starts `outlook-setup.sh` on a system without Azure CLI. 2. The script displays the `curl | sudo bash` installation command. 3. The user follows the displayed instruction. 4. `curl` follows redirects and retrieves the current remote installer. 5. The response is passed directly to `sudo bash` without validation. 6. If the upstream installer, redirect destination, delivery infrastructure, or trust chain is compromised, attacker-controlled commands execute as root. ### Impact Assessment Successful exploitation provides unrestricted root-level code execution. An attacker could read or alter all local files, extract Outlook and Azure credentials, install persistent services, modify system tools, or compromise other users and applications on the host. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

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

Attachment Names Permit Path Traversal and Arbitrary File Overwrite

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 attachment name obtained from email metadata is appended directly to the caller-selected output directory. The code does not: - Reject absolute paths. - Reject `..` path components. - Reduce the name to a safe basename. - Canonicalize and verify that the final path remains under the intended directory. - Refuse existing files. ...[truncated 1289 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/outlook-mail.sh:113
Finding

Untrusted Arguments Are Concatenated into JSON Request Bodies

Content
View full analysis
" exit 1 fi RESULT=$(curl -s -w "\n%{http_code}" -X POST "$API/sendMail" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"message\": { \"subject\": \"$SUBJECT\", \"body\": {\"contentType\": \"Text\", \"content\": \"$BODY\"}, \"toRecipients\": [{\"emailAddress\": {\"address\": \"$TO\"}}] } }") ``` Representative calendar-creation code: ```bash LOCATION_JSON="" if [ -n "$LOCATION" ]; then LOCATION_JSON=",\"location\": {\"displayName\": \"$LOCATION\"}" fi curl -s -X POST "$API/calendar/events" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"subject\": \"$SUBJECT\", \"start\": {\"dateTime\": \"$START\", \"timeZone\": \"Europe/Madrid\"}, \"end\": {\"dateTime\": \"$END\", \"timeZone\": \"Europe/Madrid\"} $LOCATION_JSON }" | jq '{status: "event created", subject: .subject, start: .start.dateTime[0:16], end: .end.dateTime[0:16], id: .id[-20:]}' ``` ...[truncated 1790 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/outlook-setup.sh:187
Finding

OAuth Authorization Response Is Not Correlated or Validated

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (72)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill includes explicit token and credential lifecycle operations, including printing the raw access token and storing client secrets and refresh tokens locally, which are not reflected in the high-level description. This concealment materially changes the trust boundary: a user expecting mail/calendar management may unknowingly grant a skill that can expose reusable credentials and facilitate account compromise.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill includes explicit token and credential lifecycle operations, including printing the raw access token and storing client secrets and refresh tokens locally, which are not reflected in the high-level description. This concealment materially changes the trust boundary: a user expecting mail/calendar management may unknowingly grant a skill that can expose reusable credentials and facilitate account compromise.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill includes explicit token and credential lifecycle operations, including printing the raw access token and storing client secrets and refresh tokens locally, which are not reflected in the high-level description. This concealment materially changes the trust boundary: a user expecting mail/calendar management may unknowingly grant a skill that can expose reusable credentials and facilitate account compromise.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

A command that prints the raw access token directly creates a straightforward credential disclosure path. Anyone able to invoke or observe this command can reuse the bearer token to access the victim's mailbox and calendar with the granted Microsoft Graph scopes until expiry, and potentially chain that with refresh-token access for longer compromise.

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
94% confidence
Finding

The documentation states that client secrets, access tokens, and refresh tokens are stored in local files under the user's home directory. Local file storage of reusable credentials is dangerous because any other process, user, backup system, or agent with filesystem access could exfiltrate them and gain persistent access to the user's Microsoft account.

Content

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

md
## Files

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

## Permissions

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The guide causes OAuth tokens to be saved to credentials.json on disk, creating a credential-access target for local attackers, malware, or accidental disclosure. Because the stored data likely includes a refresh token, compromise can provide sustained access to mail and calendar beyond a single session.

Content

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

curl -s -X POST "https://login.microsoftonline.com/$TENANT_ID/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
95% confidence
Finding

The credentials.json file is explicitly retained after token acquisition, which preserves bearer credentials on disk for later reuse. In the context of an email/calendar integration, theft of this file can expose sensitive communications, attachments, and scheduling data.

Content

Scanner excerpt · references/setup.md (reported line 106)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
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 201)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 225)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 139)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
81% confidence
Finding

The script relies on a bearer token stored in a predictable local file path under the user's home directory. If file permissions are weak, the host is multi-user, or another process can read that location, the token could be stolen and used to access or modify the victim's Outlook data through Microsoft Graph.

Content

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

sh
# Usage: outlook-calendar.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 · references/setup.md (reported line 112)May include surrounding context.

md
# 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 63)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
96% confidence
Finding

The script is explicitly designed to create and persist credentials.json containing OAuth tokens for Outlook access. Because those tokens may allow reading mail, sending mail, and accessing calendars—and refresh tokens may preserve access over time—the file becomes a high-value local secret whose theft could directly compromise the user's Microsoft account data.

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
98% confidence
Finding

The command shown fetches a script over the network and immediately executes it with root privileges. In a setup script for an Outlook integration, this is unrelated to core mail/calendar functionality and introduces a serious supply-chain and arbitrary code execution risk on the host system.

Content

Scanner excerpt · scripts/outlook-setup.sh (reported line 30)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
97% confidence
Finding

Chaining a remote download directly into sudo bash combines untrusted network input with immediate privileged execution, which is a classic unsafe command pattern. If the downloaded content is altered or malicious, the user could grant full system compromise during what appears to be a routine prerequisite step.

Content

Scanner excerpt · scripts/outlook-setup.sh (reported line 30)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

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The help text explicitly advertises a command that prints the current access token, reinforcing an insecure interface for exposing bearer credentials. In this skill's context, the token grants direct Microsoft Graph access to email and calendar functions, so disclosure can enable mailbox reading, message sending, and calendar manipulation.

Content

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

sh
*)
        echo "Usage: outlook-token.sh [refresh|get|test]"
        echo "  refresh - Refresh the access token"
        echo "  get     - Print current access token"
        echo "  test    - Test the connection"
        ;;
esac

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill exposes shell-based capabilities but does not declare any explicit tool scope or allowed-tools restrictions. In a skill that can read, send, delete mail and manage OAuth material, missing scope boundaries increases the chance the agent invokes shell commands more broadly than intended, enabling abuse or accidental execution paths.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The activation text is broad enough to match many common email or scheduling requests, which can cause over-triggering of a powerful skill. Because this skill includes read/write mail, send, delete, token, and calendar actions, broad routing raises the risk of invoking sensitive capabilities in contexts where the user did not intend to authorize them.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The setup process creates an app registration, grants broad mail/calendar permissions, and persists tenant context and credentials for future reuse. That persistence increases the blast radius of compromise because a one-time authorization can become long-lived delegated access, especially when paired with locally stored refresh tokens and client secrets.

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 (including tenant context) to `~/.outlook-mcp/`

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