Back to skill

Security audit

Windows 日历同步

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims for Outlook calendar sync, but it stores long-lived Microsoft calendar tokens in plaintext and can delete calendar events without a confirmation step.

Review before installing. Use it only if you are comfortable granting Calendars.ReadWrite and offline_access to a Microsoft app and having calendar tokens stored as a plaintext token_store.json file in the skill directory. Avoid shared machines, verify the Azure tenant/client ID before authenticating, confirm the timezone, and revoke the Microsoft app grant plus delete the token file when you stop using it.

Vulnerability Patterns
  • 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
  • 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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup_and_auth.py:136
Finding

OAuth Access and Refresh Tokens Stored in Plaintext by Setup Workflow

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/authenticate.py:105
Finding

OAuth Access and Refresh Tokens Stored in Plaintext by Authentication Workflow

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/calendar_sync.py:122
Finding

OData Filter Injection Through Unescaped Calendar Search Input

Content
View full analysis
list: """Search events by title keyword.""" now = datetime.now(_tz()) end = now + timedelta(days=days) q = urllib.parse.urlencode({ "$filter": f"contains(subject,'{query}') and " f"start/dateTime ge '{now.isoformat()}'", "$orderby": "start/dateTime", "$top": "20", }) token = get_access_token() result = _req(f"me/calendarView?{q}", token) ``` ### Technical Analysis The `query` value is inserted directly into a quoted OData expression. `urllib.parse.urlencode()` encodes the query for HTTP transport, but it does not escape OData string-literal delimiters or operators before Microsoft Graph parses the filter. An input containing a single quote and additional OData syntax can terminate the intended string literal and alter the logical expression. Depending on Microsoft Graph’s validation and supported filter behavior, crafted input may broaden the result set or generate malformed requests. The function also calculates `end` but never includes it in the filter, so the documented `days` search boundary is not enforced. This is not the injection primitive itself, but it can increase the amount of calendar data considered by an altered filter. ### Attack Path 1. An untrusted caller supplies a crafted value through `list --search`. 2. The value contains an OData quote or expression intended to terminate or modify `contains(subject, '...')`. 3. The script URL-encodes the resulting filter without escaping the OData string literal. 4. Microsoft Graph decodes and evaluates the modified filter. 5. If Graph accepts the expression, calendar events outside the intended title match may be returned. 6. The script prints subjects and start times from the ...[truncated 799 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared purpose says the skill syncs reminders to Outlook, but the documented behavior includes Azure app registration guidance, persistent storage of access/refresh tokens, and auto-refresh of those credentials. That hidden expansion of capability is dangerous because users may authorize long-lived account access and local secret storage without understanding the real trust boundary or operational behavior.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger phrases are broad enough to match ordinary conversation about reminders or calendars, which can cause the skill to activate unexpectedly. In this skill's context, accidental activation is more dangerous because activation can lead to OAuth login, network calls, local token storage, and calendar modifications or reads affecting a real user account.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill performs sensitive actions—network access to Microsoft Graph and local credential persistence—without declaring an explicit tool scope or permission boundary. This increases the chance that an agent invokes it without clear user awareness of file and network side effects, especially because it stores authentication material locally.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The invocation rules are ambiguous about when the skill should handle calendar-related requests versus when the agent should merely discuss or draft a reminder. Ambiguity is risky here because this skill has side effects in an external account, so unclear routing can result in unintended calendar reads/writes or deletion requests being executed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Hard-coding Asia/Shanghai and assuming a Chinese-user locale without opt-in can cause events to be scheduled at the wrong time, leading to missed meetings or reminders. In a calendar-writing skill, incorrect timezone handling directly affects integrity of user data and can silently propagate to all synced devices.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code silently creates config.txt with a hardcoded Azure Tenant ID when the file is absent, contradicting the documented behavior that it only reads configuration. This can bind authentication to an unexpected Microsoft tenant, causing users to authenticate against the wrong organization and potentially expose calendar access to an unintended Azure app registration context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script stores access and refresh tokens in token_store.json on disk in plaintext without any warning, encryption, or permission hardening. Anyone or any local process with filesystem access to that file can reuse the tokens to access and modify the user's Outlook calendar, and the refresh token can prolong that access beyond the current session.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill metadata says it syncs reminders to Outlook calendar, but this file also exposes listing, searching, and deletion capabilities over the user's calendar. That expands the granted behavior beyond the described purpose, which can mislead users or higher-level agents into authorizing broader calendar access than expected.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI explicitly advertises a delete command even though the stated purpose is reminder/calendar sync. Undisclosed destructive functionality is dangerous because an orchestrating agent or user may invoke the skill assuming it only creates reminders, while it can also remove existing calendar data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Deletion is available as a direct command path and executes immediately without any confirmation, dry-run, or warning. In an agent setting, ambiguous parsing, prompt injection, or accidental invocation could permanently remove calendar events with no user verification step.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring and all user-facing setup instructions are written exclusively in Chinese, and the script later continues with Chinese-only prompts and status messages. This creates a language-policy concern because the skill imposes a specific language on users without any opt-in, fallback, or explanation that the skill is region-specific.

Content

No source excerpt is available for this finding.

Tainted flow: 'req' from input (line 105, user input) → urllib.request.urlopen (network output)

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

python
"scope": " ".join(SCOPES),
    }).encode()
    req = urllib.request.Request(AUTH_URL, data=data)
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read().decode())

Tainted flow: 'req' from input (line 105, user input) → urllib.request.urlopen (network output)

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

python
"scope": " ".join(SCOPES),
    }).encode()
    req = urllib.request.Request(AUTH_URL, data=data)
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read().decode())

Tainted flow: 'req' from input (line 105, user input) → urllib.request.urlopen (network output)

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

python
"scope": " ".join(SCOPES),
    }).encode()
    req = urllib.request.Request(AUTH_URL, data=data)
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read().decode())

Tainted flow: 'req' from input (line 201, user input) → urllib.request.urlopen (network output)

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

python
}).encode()
                    req = urllib.request.Request(TOKEN_URL, data=data)
                    try:
                        with urllib.request.urlopen(req) as resp:
                            new_token = json.loads(resp.read().decode())
                            new_token["_expires_at"] = time.time() + new_token.get("expires_in", 3600)
                            save_token(new_token)

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest description says the skill is used to sync reminders or add items to the calendar, emphasizing direct writing to the user's Outlook calendar. However, the file later documents additional capabilities to query weekly schedules and delete existing events, which go beyond a narrow 'sync reminders' description.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The workflow section describes a single operational flow ending with calling calendar_sync.py add and telling the user the event was created. Elsewhere, the document explicitly states the skill also supports querying calendars and deleting events, so this workflow description contradicts the broader documented behavior rather than merely omitting details.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

Natural-language strings in the module docstring and runtime output are written only in Chinese, with no option for the user to choose another language. The policy explicitly calls out language or locale constraints as violations when they are forced without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

User-facing docstrings, CLI descriptions, help text, and printed output are all hard-coded in Chinese throughout the file. This forces a specific language/locale experience without indicating user choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.