Back to skill

Security audit

iCloud CalDav

Security checks for vulnerabilities and agentic risk

Overview

This iCloud Calendar skill is mostly purpose-aligned, but it handles Apple credentials and destructive calendar deletions with insufficient safeguards.

Review this skill before installing. Use a revocable Apple app-specific password, avoid delete operations unless you have verified the exact event target, and prefer a version that validates Apple CalDAV hostnames, restricts deletion filenames to safe .ics basenames, parses UID values exactly, and confirms destructive actions.

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

Error
Location
scripts/caldav.py:114
Finding
Apple credentials can be disclosed to untrusted server-provided hosts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/caldav.py`, lines 48–60, 114–116, 133–136, 184, 227–228, and 404–405 **Vulnerability Type**: Insufficient destination validation for authenticated network requests **Risk Level**: High ### Vulnerable Code ```python self.base_url = "https://caldav.icloud.com" self.session = requests.Session() self.session.auth = self.auth self.session.headers.update({ 'Content-Type': 'text/xml; charset=utf-8' }) ``` ```python # If principal is full URL, extract base if principal.startswith('https://'): parsed = urlparse(principal) self.base_url = f"{parsed.scheme}://{parsed.netloc}" principal = parsed.path ``` ```python if href.startswith('https://'): self._calendar_home = href parsed = urlparse(href) self.base_url = f"{parsed.scheme}://{parsed.netloc}" return href ``` ```python 'url': self.base_url + href if not href.startswith('https') else href, ``` ```python event_url = self.base_url + href if not href.startswith('https') else href event_response = self.session.get(event_url) ``` ```python event_url_full = self.base_url + href if not href.startswith('https') else href event_response = self.session.get(event_url_full) ``` ### Technical Analysis The client stores the Apple ID and app-specific password as Basic Authentication credentials on a shared `requests.Session`. Requests made through that session can therefore include the credentials automatically. Although the initial destination is `https://caldav.icloud.com`, absolute URLs returned in CalDAV XML responses are trusted based only on whether they begin with `https://`. The hostname, port, and relationship to the Apple CalDAV service are not validated. A server-provided principal, calendar-home URL, calendar URL, or event URL can consequently redirect subsequent authenticated requests to another HTTPS origin. This behavior exceeds the declared minimum privilege boundary. The Skill documentation states that credentials ...[truncated 1368 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define an explicit allowlist for `caldav.icloud.com` and documented Apple CalDAV shard hostname patterns. 2. Before every request, parse the final URL and validate: - The scheme is exactly `https`. - The hostname is an approved Apple CalDAV hostname. - The port is absent or is the expected HTTPS port. - User-information fields, fragments, and malformed host representations are absent. 3. Do not update `self.base_url` from an absolute response URL until its origin has passed validation. 4. Reject untrusted absolute `href` values rather than sending an authenticated request to them. 5. Disable redirects or inspect each redirect destination before following it. Never forward authentication across origins. 6. Consider constructing authorization headers only after destination validation instead of storing credentials globally on a reusable session. 7. Add tests covering external hosts, deceptive suffixes, nonstandard ports, encoded host representations, and cross-origin redirects. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/caldav.py:385
Finding
Path traversal in filename-based event deletion can target unintended resources<![CDATA[ ## Vulnerability Details **File Location**: `scripts/caldav.py`, lines 385–386 and 414–415 **Vulnerability Type**: URL path traversal in an authenticated destructive operation **Risk Level**: High ### Vulnerable Code ```python if filename: # Direct filename deletion event_url = calendar['url'].rstrip('/') + '/' + filename ``` ```python if not event_url: raise Exception("Event not found") # Delete the event response = self.session.delete(event_url) ``` ### Technical Analysis The `filename` argument is concatenated directly onto the selected calendar URL and used as the destination of an authenticated HTTP `DELETE` request. The code does not require the value to be a single `.ics` basename and does not reject: - `..` path components. - Forward or backward path separators. - Percent-encoded traversal sequences. - Query strings or fragments. - Absolute-path-like input. - Non-calendar resource names. HTTP clients and servers can normalize dot segments before routing the request. A value containing traversal components can therefore escape the intended calendar collection and address another resource reachable under the authenticated CalDAV namespace. Because `DELETE` is destructive and the documentation states that deletion is permanent, strict resource confinement is required. ### Attack Path 1. An attacker influences or supplies the value passed through `--file`. 2. The attacker uses a crafted value containing path traversal or URL control characters, for example a path with `../` components. 3. The client appends that value to the chosen calendar URL without validation. 4. URL normalization resolves the resulting path outside the selected calendar collection. 5. The authenticated session issues `DELETE` against the normalized resource. 6. If the account is authorized to delete that resource, the server permanently removes it. ### Impact Assessment Exploitation can delete a resource other than the event file the user intended to r ...[truncated 376 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat `--file` strictly as a basename, not as a URL or path. 2. Apply an allowlist such as `[A-Za-z0-9._-]+\.ics`, with an appropriate length limit. 3. Reject: - `/` and `\`. - `.` and `..` path components. - Percent-encoded characters. - Query delimiters and fragments. - Control characters and whitespace normalization ambiguities. 4. Construct the URL with a safe URL-joining mechanism. 5. Parse and normalize the resulting URL, then verify that: - Its origin exactly matches the validated calendar origin. - Its parent path is exactly the selected calendar collection. - It is an immediate child rather than a nested or traversed path. 6. Fetch and verify the target event before deletion. 7. Require explicit user confirmation that displays the event title, UID, calendar, and date before issuing the permanent `DELETE`. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/caldav.py:397
Finding
Substring-based UID matching can delete the wrong calendar event<![CDATA[ ## Vulnerability Details **File Location**: `scripts/caldav.py`, lines 397–408 and 414–415 **Vulnerability Type**: Improper event identifier validation in a destructive operation **Risk Level**: High ### Vulnerable Code ```python for response in root.findall('.//{DAV:}response'): href = self._href(response) if not href.endswith('.ics'): continue # Fetch event and check UID event_url_full = self.base_url + href if not href.startswith('https') else href event_response = self.session.get(event_url_full) if event_response.status_code == 200 and uid in event_response.text: event_url = event_url_full break ``` ```python if not event_url: raise Exception("Event not found") # Delete the event response = self.session.delete(event_url) ``` ### Technical Analysis The deletion routine does not parse the event's `UID` property and compare it to the requested UID. Instead, it performs a case-sensitive substring search across the complete raw ICS document: ```python uid in event_response.text ``` The supplied value may match: - Only part of another event's UID. - An event title. - A description. - A location. - Another arbitrary ICS property. The routine selects the first matching event returned by the server and deletes it. Consequently, even a syntactically valid but non-unique partial identifier can cause deletion of an unrelated event. ### Attack Path 1. A user or attacker supplies a short, partial, or crafted value through `--uid`. 2. The client downloads each `.ics` resource in the selected calendar. 3. The supplied string occurs somewhere in an unrelated event's raw ICS content, such as its description or as part of its actual UID. 4. The unrelated event becomes the first substring match. 5. The client stores that event's URL and stops searching. 6. An authenticated `DELETE` request permanently removes the incorrectly matched event. ### Impact Assessment Exploitation can cause deletion of an a ...[truncated 454 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse every ICS document with a standards-compliant iCalendar parser. 2. Locate the relevant `VEVENT` component and retrieve its `UID` property. 3. Compare the complete normalized UID using exact equality rather than substring matching. 4. Reject missing, empty, excessively long, or syntactically invalid UID inputs. 5. Handle calendar objects containing multiple components explicitly instead of accepting the first incidental match. 6. If multiple exact matches are found, stop and report an ambiguity rather than deleting any event. 7. Before deletion, display the matched event's title, date, calendar, and exact UID and require explicit confirmation. 8. Where supported, use a server-side CalDAV query that filters on the exact UID, followed by local exact verification. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code aligns closely with the stated iCloud Calendar/CalDAV purpose and correctly uses direct CalDAV access with Apple credentials. It supports reading calendars/events, creating events, and deleting events. However, the description explicitly claims create, read, update, and delete functionality, while the code only implements create, read, and delete; there is no event update/edit operation. Additionally, the description mentions using it to 'find free time' or manage schedule, but the code only lists events within a date range and does not compute availability or free-time slots. Because a declared core capability (update) is missing, this is a description-behavior mismatch.

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/caldav.py list-calendars
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Delete Event

```
DELETE /12345678/calendars/CalendarName/event-uuid.ics
```

## iCalendar (ICS) Format
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill requires access to environment variables for Apple credentials and network access to Apple's CalDAV endpoint, but it does not explicitly declare any tool scope or permissions. This creates an authorization ambiguity where a host agent may grant broader capabilities than intended, making credential access and outbound network use insufficiently constrained.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This markdown file includes concrete instructions for PUT and DELETE requests that create, overwrite, and remove calendar events. Under the markdown-specific warning criterion, the description omits any caution that these actions affect user data and may overwrite or permanently delete calendar entries.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The fallback ICS generator hard-codes DTSTART/DTEND with TZID=Asia/Shanghai, regardless of the user's actual timezone or input semantics. This can silently create events at the wrong time, causing missed meetings or unintended scheduling actions; in a calendar-management skill, that operational integrity issue is security-relevant because it can alter user data incorrectly.

Context-Inappropriate Capability

Low
Confidence
81% confidence
Finding
The manifest describes an iCloud Calendar integration for managing events, but does not mention reading secrets from the runtime environment. Accessing environment variables is a separate sensitive capability that goes beyond direct calendar operations, even if used here for authentication.

Static analysis

No suspicious patterns detected.