# CalDAV Calendar plugin

The CalDAV Calendar plugin lets a Vaubaan Gateway mission use CalDAV Calendar without handing the agent a credential. Calendars on any CalDAV server (iCloud, Fastmail, Nextcloud…), connected with an app password: list calendars and events, read, create, change and delete events, under risks zoned by who the attendees are. Not for Google Calendar.

- Version: `0.1.0` (package `@vaubaan/plugin-caldav`)
- Health: not enough reports yet — [what this means](/plugins/health)
- Source: [plugins/caldav](https://github.com/vaubaan/gateway/tree/main/plugins/caldav), catalog [risk-catalog.yaml](https://github.com/vaubaan/gateway/blob/main/plugins/caldav/src/risk-catalog.yaml) version 1 of 2026-10-27
- How to connect an account: [Connect CalDAV Calendar](/docs/providers/caldav)
- How it is modelled: [handbook](https://github.com/vaubaan/gateway/blob/main/docs/handbook/providers/caldav.md)

One account is one CalDAV account (a server URL, a username and an app password); each calendar that stores events is a resource. Reads are priced by the length of the time range; writes by whether they create, change or delete an event, and by who the server may notify: attendees inside the company domains, on the allowlist, or outside. Google Calendar is a separate service.

## Permissions

Each permission is a named risk of the plugin's catalog: a mission holds an explicit list of them, never "all". The severity is computed from the permission's six axes (undo, blast radius, data, cost, visible to, lasts); nothing is decided from it.

| Permission | What it allows | Severity | Why it is a risk |
| --- | --- | --- | --- |
| `caldav.read-calendars` | List the calendars (names, descriptions) | low | The calendars of the mission, with their names and descriptions as the server holds them. Metadata only, no event. |
| `caldav.read-events` | Read events (times, titles, places, descriptions, attendees) | low | Events over a time range of at most 31 days, or one event by its id : what the account does and with whom, places and descriptions included. Invitations land in a calendar without being asked for, so a description may be written by a stranger : read it as untrusted text (prompt injection, OWASP LLM01). |
| `caldav.read-wide-range` | Read events over a wide time range (more than 31 days) | medium | One call returns up to 200 events over up to 366 days : a long stretch of agenda — habits, recurring meetings, who is met how often — at once. Needed beside \`caldav.read-events\` for any range longer than 31 days. |
| `caldav.event-create` | Create events | low | Adds an event to the calendar. Reversible : the event can be deleted. Alone it concerns the account only ; inviting people also needs the \`attendees-\*\` permission of their zone. |
| `caldav.event-change` | Change events (time, title, place, description, attendees) | low | Rewrites an existing event, read first and written back only if it did not change in between (\`If-Match\`). The previous version is not kept. Changing an event others attend sends them an update : the \`attendees-\*\` permission of their zone is needed too. Invitations organized by somebody else are never changed. |
| `caldav.event-delete` | Delete events | medium | Removes an event, recurring series included : CalDAV keeps no bin and no history. Deleting a meeting others attend sends them a cancellation, and deleting an invitation sends its organizer a decline : the \`attendees-\*\` permission of their zone is needed too. |
| `caldav.attendees-internal` | Invite, update or cancel attendees inside the company domains | medium | The write concerns colleagues only (addresses on the internal domains of the calendar) : the server may mail them an invitation, an update or a cancellation. Visible to the team, not outside. |
| `caldav.attendees-allowlisted` | Invite, update or cancel attendees on the allowlist | medium | The write concerns pre-approved contacts outside the company (the allowlisted addresses and domains of the calendar), colleagues possibly with them. The server may mail them : a message sent cannot be taken back. |
| `caldav.attendees-external` | Invite, update or cancel attendees outside the company and the allowlist | medium | The write concerns at least one address neither internal nor allowlisted (or that the plugin cannot read as one address). The server may mail an invitation carrying the title, time, place and description of the event to anybody : an exfiltration path, and a message in the company's name. Ask me first is recommended. |
| `caldav.uncategorized-write` | Uncategorized CalDAV write | high (the catch-all: touched only by a call no other permission covers) | Catch-all for writes no entry above covers. No tool of the plugin reaches it today : a new write (a calendar created, an invitation answered) lands here until it has its own permission. Never offered in a preset. |

## Presets

A preset pre-fills the permissions of a mission for one account, with a limit per period, a rate and whether each permission runs freely or asks the mission creator first. The person creating the mission adjusts it; the mission stores the explicit list.

### Read-only

`read-only` — List the calendars and read events over up to 31 days at a time; no change, nobody notified.

| Permission | What it allows | Limit per period | Rate | Runs |
| --- | --- | --- | --- | --- |
| `caldav.read-calendars` | List the calendars (names, descriptions) | 500 | 60 per minute | runs freely |
| `caldav.read-events` | Read events (times, titles, places, descriptions, attendees) | 1000 | 60 per minute | runs freely |

### Own agenda

`own-agenda` — Read-only, plus creating and changing events that concern nobody else, so no invitation, update or cancellation is sent; deleting an event asks first.

| Permission | What it allows | Limit per period | Rate | Runs |
| --- | --- | --- | --- | --- |
| `caldav.read-calendars` | List the calendars (names, descriptions) | 500 | 60 per minute | runs freely |
| `caldav.read-events` | Read events (times, titles, places, descriptions, attendees) | 1000 | 60 per minute | runs freely |
| `caldav.event-create` | Create events | 100 | 10 per minute | runs freely |
| `caldav.event-change` | Change events (time, title, place, description, attendees) | 100 | 10 per minute | runs freely |
| `caldav.event-delete` | Delete events | 20 | 5 per minute | ask me first |

### Scheduling assistant

`assistant` — Own agenda, plus reading wide time ranges and meetings with colleagues and allowlisted contacts; inviting anybody else and deleting an event ask first.

| Permission | What it allows | Limit per period | Rate | Runs |
| --- | --- | --- | --- | --- |
| `caldav.read-calendars` | List the calendars (names, descriptions) | 500 | 60 per minute | runs freely |
| `caldav.read-events` | Read events (times, titles, places, descriptions, attendees) | 2000 | 60 per minute | runs freely |
| `caldav.read-wide-range` | Read events over a wide time range (more than 31 days) | 50 | 5 per minute | runs freely |
| `caldav.event-create` | Create events | 200 | 20 per minute | runs freely |
| `caldav.event-change` | Change events (time, title, place, description, attendees) | 200 | 20 per minute | runs freely |
| `caldav.event-delete` | Delete events | 50 | 5 per minute | ask me first |
| `caldav.attendees-internal` | Invite, update or cancel attendees inside the company domains | 200 | 20 per minute | runs freely |
| `caldav.attendees-allowlisted` | Invite, update or cancel attendees on the allowlist | 100 | 10 per minute | runs freely |
| `caldav.attendees-external` | Invite, update or cancel attendees outside the company and the allowlist | 20 | 5 per minute | ask me first |

## Tools

| Tool | What it does |
| --- | --- |
| `caldav__list_calendars` | List the calendars |
| `caldav__list_events` | List the events of a time range |
| `caldav__get_event` | Read an event |
| `caldav__create_event` | Create an event |
| `caldav__update_event` | Change an event |
| `caldav__delete_event` | Delete an event |

## Health

Health: not enough reports yet. A plugin version is deemed validated by the community with at least 200 reports and 90 % of them successful, over the last 90 days, as reported by the instances whose operators turned community telemetry on. It is a community signal, not a security guarantee.
