Back to skill

Security audit

outlook-calendar-management

Security checks for vulnerabilities and agentic risk

Overview

This Outlook calendar skill largely matches its purpose, but normal use can automatically install unpinned Python packages while the skill handles calendar-write OAuth tokens.

Review this skill before installing if you do not want an agent-run calendar tool to modify your Outlook calendar or install Python packages automatically. Use a dedicated Python environment, consider preinstalling pinned dependencies yourself, protect or relocate the OAuth token file with OCAL_TOKEN_PATH, verify the signed-in account with status before writes, and revoke the Microsoft consent if you stop using it.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
scripts/ocal_bootstrap.py:14
Finding

Automatic Runtime Installation of Unpinned Dependencies

Content
View full analysis

Vulnerability Details

File Location: scripts/ocal_bootstrap.py:14-15, 38-49
Vulnerability Type: Unverified and unpinned runtime dependency installation
Risk Level: Medium

Vulnerable Code

python
# Dependencies: requests (Graph requests), msal (authentication renewal),
# and tzdata (Windows timezone data)
REQUIRED = ("requests", "msal", "tzdata")


def ensure_deps():
    """Check dependencies and install missing packages automatically."""
    missing = _missing()
    if not missing:
        return
    pkgs = " ".join(missing)
    print(t("deps_missing", pkgs=pkgs), file=sys.stderr)
    print(t("deps_installing"), file=sys.stderr)
    try:
        proc = subprocess.run(
            [sys.executable, "-m", "pip", "install",
             "--disable-pip-version-check", *missing],
            capture_output=True, text=True, timeout=300,
        )

Technical Analysis

The application automatically invokes pip install when requests, msal, or tzdata is absent. No exact versions, package hashes, lockfile, trusted index, or repository verification is specified. Installation also occurs as part of ordinary login and calendar-command execution rather than through a separate, explicit setup process.

The package names appear legitimate and no typo-squatting was identified. Nevertheless, dependency resolution uses the Python environment's currently configured package indexes and selects whatever compatible versions are available at execution time. Consequently, the effective code executed by the Skill can change after the Skill package has been audited.

This is a supply-chain weakness rather than direct command injection: package names are fixed constants and subprocess.run uses an argument list without shell=True. Exploitation would require compromise or unsafe configuration of the package source, a malicious package release, or compromise of a transitive dependency.

Atta

...[truncated 1512 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove automatic package installation from normal login and calendar operations.
  2. Move dependency installation to a separate, explicit setup step that requires user approval.
  3. Pin all direct and transitive dependencies to reviewed versions in a lockfile.
  4. Generate and verify cryptographic hashes for every distributable package, then install with pip install --require-hashes.
  5. Configure an explicit trusted package index or an internally controlled package mirror instead of inheriting arbitrary environment-level index configuration.
  6. Install dependencies in an isolated virtual environment with only the permissions required by the Skill.
  7. Add automated dependency vulnerability and integrity scanning to the release process.
  8. Document the reviewed dependency versions and update them through a controlled, auditable process.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (42)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This code chunk does not implement Outlook calendar management or interact with Microsoft services at all. It computes local time metadata (current datetime, today, timezone, UTC offset, weekday, week start) and date offsets, which are generic helper functions rather than the declared primary purpose. The module docstring explicitly says there is no authentication or Graph calls, reinforcing that it cannot perform the described calendar operations. Therefore the description materially overstates and misrepresents the actual behavior of this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Most of the code matches the declared purpose very well: it lists/searches events, adds/updates/deletes/moves them, reads event details, supports recurring events, and computes free time, all against Outlook/Microsoft calendar resources. However, the code also implements a status command that checks authentication state, reads token expiry, calls /me/calendar, and reports the current account email/address and date context. In addition, it calls /me/mailboxSettings?$select=timeZone to retrieve mailbox time zone preferences. These are Outlook-related supporting behaviors, but they are still capabilities not explicitly represented in the declared description, especially the account/connection status reporting. So this is a small but real description/behavior mismatch rather than a major one.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description says the skill manages Outlook calendar events, but the provided code chunk only handles authentication/bootstrap for connecting an Outlook account. It initiates a Microsoft device-code flow, prompts the user to visit microsoft.com/link, acquires tokens, and writes token data locally with restricted permissions. There is no code for viewing, finding, adding, updating, moving, deleting, recurring-event handling, or free-time queries. While authentication can be a supporting detail for a calendar skill overall, this specific chunk's actual behavior is materially different from the declared primary purpose and exposes an undeclared capability: credential/token acquisition and storage.

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

python
def get_token():
    """拿一个能用的访问令牌:没过期直接返回,过期了用 refresh token 续。

    :return: access token 字符串;还没认证过返回 None
    :raises CalError: token 文件损坏 / 没有 refresh token / 续期失败
    """
    if not os.path.exists(TOKEN_PATH):

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/ocal_auth.py (reported line 117)May include surrounding context.

python
def get_token():
    """拿一个能用的访问令牌:没过期直接返回,过期了用 refresh token 续。

    :return: access token 字符串;还没认证过返回 None
    :raises CalError: token 文件损坏 / 没有 refresh token / 续期失败
    """
    if not os.path.exists(TOKEN_PATH):

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/ocal_auth.py (reported line 122)May include surrounding context.

python
def get_token():
    """拿一个能用的访问令牌:没过期直接返回,过期了用 refresh token 续。

    :return: access token 字符串;还没认证过返回 None
    :raises CalError: token 文件损坏 / 没有 refresh token / 续期失败
    """
    if not os.path.exists(TOKEN_PATH):

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

L62 规定“语言优先级为 --lang → OCAL_LANG → 系统探测”,意味着在未获得用户显式选择时,技能会依据环境变量或系统设置决定语言。根据规则,强制或默认施加语言/地区策略且缺少用户 opt-in 可能构成自然语言政策违规。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README explicitly states that device-code sign-in stores credentials at ~/.outlook_cal_token.json, but it does not prominently warn users that this file contains sensitive OAuth tokens that grant calendar access and must be protected. On multi-user systems, shared environments, backups, or compromised home directories, token theft could let an attacker read or modify the user's Outlook calendar without re-authentication.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill instructs the agent to execute local Python and perform authenticated Microsoft Graph operations, but it does not declare any explicit tool or permission scope. That creates an authorization-boundary problem: a host agent may allow broader shell, file, environment, and network access than users expect from the metadata, increasing the chance of unintended command execution or data access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill supports destructive and modifying actions like update, move, and delete, but the user-facing guidance does not require an explicit confirmation or warning before irreversible changes. In an agent setting, this can lead to accidental calendar data loss or unintended modifications from ambiguous prompts or misresolved targets, especially with recurring events.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The text says Chinese conversations must use --lang zh and other languages must use --lang en, which imposes a fixed language policy rather than offering a user choice. This can violate language/locale policy because non-Chinese users are funneled into English with no opt-in or documented justification for excluding other locales.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file contains natural-language instructions that require a specific account type: '使用 Outlook 账户登录' and '仅个人 Microsoft 帐户'. Under the policy rule, forcing a specific language/locale or equivalent user-context choice without opt-in should be flagged unless clearly justified; here the document does not present alternatives or explicit opt-in framing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation states that reconnecting will overwrite the current calendar connection and that all operations sync in real time to the same live calendar, but it does not prominently warn users about the risk of modifying or deleting production calendar data. In a calendar-management skill with write/delete capabilities, missing a clear warning or confirmation step increases the chance of accidental destructive actions against the wrong account.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill metadata says it does not handle email or other Outlook data, yet the requested scopes include MailboxSettings.Read in addition to Calendars.ReadWrite. Even if used only to determine timezone preferences, this is a privilege expansion beyond the stated purpose and increases data exposure if the token is compromised or the capability is later misused.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Reading mailbox settings adds a non-calendar Outlook capability that is not clearly aligned with the declared calendar-only purpose. This mismatch can mislead users about what data the skill may access and broadens the blast radius of the stored tokens.

Content

No source excerpt is available for this finding.

Tainted flow: 'tmp' from os.environ.get (line 137, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/ocal_auth.py (reported line 139)May include surrounding context.

python
# 先写临时文件再原子替换:写入中途崩溃不会把 token 文件写坏成半截 JSON
        tmp = TOKEN_PATH + ".tmp"
        try:
            with open(tmp, 'w', encoding='utf-8') as f:
                json.dump(result, f, ensure_ascii=False)
            try:
                os.chmod(tmp, 0o600)  # token 含 access/refresh token,收紧权限

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The natural-language content in the module docstring is entirely in Chinese, and the file imports an i18n helper but does not document any user language choice here. Under the stated policy, forcing a specific language without opt-in can be a locale/language policy violation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill automatically installs Python packages at runtime, which exceeds the expected scope of a calendar-management capability and mutates the host environment without explicit consent. This creates supply-chain and integrity risk: a compromised package source, dependency confusion, or unexpected environment changes could lead to code execution or unstable behavior on the system running the skill.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/ocal_bootstrap.py (reported line 47)May include surrounding context.

python
print(t("deps_missing", pkgs=pkgs), file=sys.stderr)
    print(t("deps_installing"), file=sys.stderr)
    try:
        proc = subprocess.run(
            [sys.executable, "-m", "pip", "install", "--disable-pip-version-check", *missing],
            capture_output=True, text=True, timeout=300,
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file’s only user-facing natural-language content, including the module and class docstrings, is entirely in Chinese. The provided policy flags language or locale constraints when a skill forces a specific language without user opt-in, and this file contains no indication of language selection or region-specific justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module-level docstring states the command implementation description entirely in Chinese, and the user-facing strings throughout the file are routed through Chinese-localized text helpers. There is no visible mechanism in this file for offering a language choice or requiring explicit user opt-in to a Chinese-only locale, which can violate language/locale policy for general-purpose skills.

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 manages Outlook calendar events and does not handle other Outlook product areas, but this helper calls the non-calendar /me/mailboxSettings endpoint to read mailbox preferences. Even though used for timezone handling, this is behavior beyond the stated calendar-only description.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The natural-language content in the module docstring and throughout the file is exclusively in Chinese, which indicates the skill is oriented to a single language without any visible opt-in or alternative locale choice in this file. Under the stated policy, forcing a specific language without user choice is a natural-language policy concern unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring states the language priority ends with a default of zh, and the code sets DEFAULT_LANG = "zh". This creates a language-policy concern because users who do not provide --lang or OCAL_LANG may receive Chinese output by default rather than being offered a neutral default or explicit choice.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/ocal_i18n.py (reported line 373)May include surrounding context.

python
"err_end_after_start": "End time must be after start time",
        "confirm_prompt": "   Confirm? [y/N] ",
        "cancel": "🚫 Cancelled",
        "cancel_eof": "\n🚫 Cancelled (non-interactive; use -y to skip confirmation)",
        "cancel_eof_delete": "\n🚫 Cancelled (non-interactive; use -y or --series)",
        "importance_line": "   ⭐ Importance: {v}",
        "private_line": "   🔒 Private",

Static analysis

No suspicious patterns detected.