Back to skill

Security audit

outlook-todo

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Microsoft To Do integration with persistent Microsoft Graph tokens and guarded task writes, with some low-risk over-permission and unused helper-code residue to review.

Install only if you are comfortable granting this skill ongoing delegated access to read and modify your Microsoft To Do tasks. Treat ~/.outlook-todo as sensitive because it stores refresh tokens, use token.sh clear when done, and consider reducing User.Read in a future version if profile validation is not needed.

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

T05 · Unauthorized Access and Privilege Escalation

Note
Location
scripts/setup-device-code.sh:109
Finding

Unnecessary User.Read Permission and Profile Data Retrieval

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
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the advertised write functionality, dedicated device-code auth flow, and confirmation safeguards are absent from the real code, users and orchestration systems may make incorrect trust decisions about what the skill can and cannot do. While this second mismatch report appears partly inconsistent with the markdown itself and may reflect scanner confusion across code chunks, any real divergence between documented safety controls and implemented behavior is security-relevant because it defeats informed approval.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the advertised write functionality, dedicated device-code auth flow, and confirmation safeguards are absent from the real code, users and orchestration systems may make incorrect trust decisions about what the skill can and cannot do. While this second mismatch report appears partly inconsistent with the markdown itself and may reflect scanner confusion across code chunks, any real divergence between documented safety controls and implemented behavior is security-relevant because it defeats informed approval.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `SKILL.md` | this file |

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

sh
#!/usr/bin/env bash
# scripts/token.sh
# Inspect or refresh the Microsoft Graph access token used by outlook-todo.
#
# Subcommands:
#   status    Show token presence & expiry (no token value ever printed).

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

sh
#!/usr/bin/env bash
# scripts/token.sh
# Inspect or refresh the Microsoft Graph access token used by outlook-todo.
#
# Subcommands:
#   status    Show token presence & expiry (no token value ever printed).

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

sh
#!/usr/bin/env bash
# scripts/token.sh
# Inspect or refresh the Microsoft Graph access token used by outlook-todo.
#
# Subcommands:
#   status    Show token presence & expiry (no token value ever printed).

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

sh
#!/usr/bin/env bash
# scripts/token.sh
# Inspect or refresh the Microsoft Graph access token used by outlook-todo.
#
# Subcommands:
#   status    Show token presence & expiry (no token value ever printed).

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

sh
#!/usr/bin/env bash
# scripts/token.sh
# Inspect or refresh the Microsoft Graph access token used by outlook-todo.
#
# Subcommands:
#   status    Show token presence & expiry (no token value ever printed).

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

sh
#!/usr/bin/env bash
# scripts/token.sh
# Inspect or refresh the Microsoft Graph access token used by outlook-todo.
#
# Subcommands:
#   status    Show token presence & expiry (no token value ever printed).

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill explicitly stores access and refresh tokens under ~/.outlook-todo/, creating persistent delegated Graph access beyond a single session. Persistent tokens increase risk if the host, user account, backups, or local files are compromised, especially because offline_access enables token renewal without re-prompting the user.

Content

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

md
name: outlook-todo
license: MIT
description: |
  Read and write Microsoft To Do via its own Microsoft Graph device-code login.
  Enumerate task lists, read/filter tasks, and create, update, complete, or delete tasks
  (writes require --apply plus a typed-YES prompt or an explicit --yes flag).
metadata:

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

md
Formats: `summary`, `json`, `ids`, `raw`.

## Write tasks (explicit confirmation required)

`todo-write.sh` supports **create / update / complete / delete**. Every write defaults to
**dry-run** (prints the JSON payload; may perform read-only Graph lookups such as

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/_lib.sh (reported line 54)May include surrounding context.

sh
}

_lib__require_bin jq
_lib__require_bin curl
# python3 is preferred for some pretty-printer paths; warn if missing
if ! command -v python3 >/dev/null 2>&1; then
    echo "outlook-todo: warning: python3 not found, table formatting will fall back to jq" >&2

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/_lib.sh (reported line 80)May include surrounding context.

sh
if [[ ! -d "$OUTLOOK_TODO_DIR" ]]; then
        mkdir -p "$OUTLOOK_TODO_DIR" || die "cannot create $OUTLOOK_TODO_DIR"
    fi
    # chmod 700; a failure here means tokens would sit on a permissive location
    if ! chmod 700 "$OUTLOOK_TODO_DIR" 2>/dev/null; then
        die "could not chmod 700 $OUTLOOK_TODO_DIR; refusing to store tokens in a permissive location"
    fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/_lib.sh (reported line 81)May include surrounding context.

sh
if [[ ! -d "$OUTLOOK_TODO_DIR" ]]; then
        mkdir -p "$OUTLOOK_TODO_DIR" || die "cannot create $OUTLOOK_TODO_DIR"
    fi
    # chmod 700; a failure here means tokens would sit on a permissive location
    if ! chmod 700 "$OUTLOOK_TODO_DIR" 2>/dev/null; then
        die "could not chmod 700 $OUTLOOK_TODO_DIR; refusing to store tokens in a permissive location"
    fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/_lib.sh (reported line 82)May include surrounding context.

sh
if [[ ! -d "$OUTLOOK_TODO_DIR" ]]; then
        mkdir -p "$OUTLOOK_TODO_DIR" || die "cannot create $OUTLOOK_TODO_DIR"
    fi
    # chmod 700; a failure here means tokens would sit on a permissive location
    if ! chmod 700 "$OUTLOOK_TODO_DIR" 2>/dev/null; then
        die "could not chmod 700 $OUTLOOK_TODO_DIR; refusing to store tokens in a permissive location"
    fi

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The natural-language comments and implementation set Asia/Shanghai as the default timezone and present it as the standard usage, which imposes a specific locale on users without offering a choice or explaining why this locale is required. This matches the policy category for language/locale constraints applied without user opt-in.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest describes a skill for reading and writing Microsoft To Do tasks and task lists, but this helper file contains event-specific functionality such as building calendar event request bodies and printing event summaries. Calendar event handling is a separate Graph domain from To Do tasks, so this behavior exceeds the described feature set rather than serving as an obvious implementation detail of task management.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The function documentation and code state that the event timezone defaults to Asia/Shanghai, which creates locale-specific behavior for all users unless they override it. There is no nearby justification that the skill is China-specific or any opt-in mechanism for this locale choice.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
79% confidence
Finding

The script intentionally requests offline_access and persists refresh/access tokens to disk, creating durable session material that can be reused if the local host or home directory is compromised. In the context of a To Do integration this is expected functionality, but the stored tokens still grant ongoing Microsoft Graph access and therefore represent a meaningful credential-theft target.

Content

Scanner excerpt · scripts/setup-device-code.sh (reported line 10)May include surrounding context.

sh
#   2. Requests exactly the minimal To Do consent set (documented in SKILL.md):
#         offline_access
#         https://graph.microsoft.com/User.Read
#         https://graph.microsoft.com/Tasks.ReadWrite
#      No shared family token store, no calendar or contacts scopes, no mail,
#      no files, no directory scopes — ever.
#   3. Calls the /devicecode endpoint and prints a short user code + verification URL.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/_lib.sh (reported line 129)May include surrounding context.

sh
#   - The device_code and verification_uri are NOT secrets (they are short-lived and
#     require the user's own credentials to redeem). They are echoed to stderr so
#     they appear in the terminal but are not logged to any file.
#   - The access_token and refresh_token are written only to tokens.json (chmod 600)
#     and NEVER echoed to stdout/stderr. The only thing printed about the token is
#     its expiry timestamp.
#   - No mail scopes are ever requested. The /me probe uses User.Read only.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/_lib.sh (reported line 156)May include surrounding context.

sh
#   - The device_code and verification_uri are NOT secrets (they are short-lived and
#     require the user's own credentials to redeem). They are echoed to stderr so
#     they appear in the terminal but are not logged to any file.
#   - The access_token and refresh_token are written only to tokens.json (chmod 600)
#     and NEVER echoed to stdout/stderr. The only thing printed about the token is
#     its expiry timestamp.
#   - No mail scopes are ever requested. The /me probe uses User.Read only.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-device-code.sh (reported line 24)May include surrounding context.

sh
#   - The device_code and verification_uri are NOT secrets (they are short-lived and
#     require the user's own credentials to redeem). They are echoed to stderr so
#     they appear in the terminal but are not logged to any file.
#   - The access_token and refresh_token are written only to tokens.json (chmod 600)
#     and NEVER echoed to stdout/stderr. The only thing printed about the token is
#     its expiry timestamp.
#   - No mail scopes are ever requested. The /me probe uses User.Read only.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-device-code.sh (reported line 164)May include surrounding context.

sh
#   - The device_code and verification_uri are NOT secrets (they are short-lived and
#     require the user's own credentials to redeem). They are echoed to stderr so
#     they appear in the terminal but are not logged to any file.
#   - The access_token and refresh_token are written only to tokens.json (chmod 600)
#     and NEVER echoed to stdout/stderr. The only thing printed about the token is
#     its expiry timestamp.
#   - No mail scopes are ever requested. The /me probe uses User.Read only.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

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

Content

Scanner excerpt · scripts/setup-device-code.sh (reported line 258)May include surrounding context.

sh
#   - The device_code and verification_uri are NOT secrets (they are short-lived and
#     require the user's own credentials to redeem). They are echoed to stderr so
#     they appear in the terminal but are not logged to any file.
#   - The access_token and refresh_token are written only to tokens.json (chmod 600)
#     and NEVER echoed to stdout/stderr. The only thing printed about the token is
#     its expiry timestamp.
#   - No mail scopes are ever requested. The /me probe uses User.Read only.

Static analysis

No suspicious patterns detected.