Skip to content
Report library
Purpose / Other

Extension Email Calendar Events Skill Security Audit

What the author says it does (original text)

Support for organising events/meetings and sending invitations by email.

Independent security check

Do not install or run it yet

Files checked
1
Risks found
3
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.Risks found: 1
Medium risk

Delivery errors are discarded, so callers cannot tell whether invitations were sent

Source references: 3
What we found

The email component explicitly returns either #ok or #err with error text, but sendEventInvitation discards that result with ignore and returns async ().

Why this matters

The application may treat the call as successful even when authorization or delivery failed. Users may make plans based on invitations that were never sent, while the error is unavailable for alerting or retry.

The email interface explicitly allows an `#err` result containing error text, but the example sender discards the awaited result with `ignore` and returns `async ()`. If the mail service rejects or fails a send, the caller cannot learn that from this function, so an administrator may wrongly assume invitations were delivered and make incorrect scheduling decisions. Users can ask for the result to be checked and returned, failures to be logged, and retry or failure notifications.

SKILL.md:130In the instructionsOpen original file
    public type SendResult = {    #ok;    #err : Text;  };  public func sendCalendarEvent(fromUsername : Text, event : CalendarEvent) : async SendResult;};
Show 2 other places
SKILL.md:309In the instructionsOpen original file
    ignore await EmailClient.sendCalendarEvent(      "no-reply",      event    );  };
SKILL.md:301In the instructionsOpen original file
  public shared ({ caller }) func sendEventInvitation(uid : Text) : async () {    if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.Risks found: 1
High risk

Unverified arbitrary addresses are automatically sent every new event’s details

Source references: 5
What we found

The public registration endpoint accepts a name and email without showing ownership verification. When an event is created, every registered profile is automatically made a required attendee; an administrator can then send the event summary, description, location, and times to those addresses.

Why this matters

Any caller can register a third party’s address. If an administrator later creates and sends an event, that party may receive internal meeting details and an unsolicited invitation; this can also be abused to direct mail to arbitrary recipients.

The example implementation supports this risk, though it is not proof of execution. Any caller can submit an email; when an admin creates an event, every stored profile is automatically made a required attendee, and the mail function sends the full event, including summary, description, location, and times. If an app adopts this example and an admin sends the invitation, an unverified or impersonated address could receive event details. Users can ask for email-ownership verification, per-event attendee selection, and recipient confirmation before sending.

SKILL.md:175In the instructionsOpen original file
  public shared ({ caller }) func registerUser(name : Text, email : Text) : async () {    // Check if the user already exists    if (userProfiles.containsKey(caller)) {      Runtime.trap("User already registered");    };    // Check if the email is already used    if (emails.contains(email)) {      Runtime.trap("Email already taken");    };    // Add a user record    userProfiles.add(      caller,      {        name;        email;      }    );    emails.add(email);  };
Show 4 other places
SKILL.md:220In the instructionsOpen original file
        },        userProfiles.values().map(          func({ name; email }) {            {              who = { name = ?name; email };              role = #required;            };          }        ).toArray()      ).isNull()
SKILL.md:94In the instructionsOpen original file
module {  public type CalendarEvent = {    uid : Text;    sequence : Nat32;    method : CalendarEventMethod;    summary : Text;    description : Text;    location : Text;    startTime : Nat64;    endTime : Nat64;    organizer : Mailbox;    attendees : [Attendee];  };
SKILL.md:306In the instructionsOpen original file
    let event = calendarEvents.get(uid)      ?? Runtime.trap("Calendar event not found");    ignore await EmailClient.sendCalendarEvent(      "no-reply",      event    );  };
SKILL.md:309In the instructionsOpen original file
    ignore await EmailClient.sendCalendarEvent(      "no-reply",      event    );  };
Could it delete files or keep running?Looks for broad file deletion, disk overwrites, and programs set to start automatically.No risks found
Could it bypass safety checks?Looks for skipped website security checks, excessive file access, or actions that skip your approval.Risks found: 1
Medium risk

First-come registration can impersonate an address and lock out its owner

Source references: 3
What we found

The caller supplies the email address, and the code only checks whether that text is already reserved before adding it to a uniqueness set. No verification message or other proof that the caller controls the address is shown.

Why this matters

An attacker can register another person’s email with any name, associate the attacker’s principal with that identity data, and cause the actual owner’s later attempt to fail with “Email already taken.”

The public example registration accepts any caller-supplied email, checks only whether that text already exists, then binds it to the caller and adds it to the uniqueness set; no ownership-verification step is shown. If implemented as written, someone could register another person's address first, causing the real owner to receive “Email already taken” later and potentially making that address an invitation recipient. No registration-side release mechanism is shown. Users can require verification by code or confirmation link before reserving an address, plus a safe recovery process.

SKILL.md:175In the instructionsOpen original file
  public shared ({ caller }) func registerUser(name : Text, email : Text) : async () {    // Check if the user already exists    if (userProfiles.containsKey(caller)) {      Runtime.trap("User already registered");    };    // Check if the email is already used    if (emails.contains(email)) {      Runtime.trap("Email already taken");    };
Show 2 other places
SKILL.md:186In the instructionsOpen original file
    // Add a user record    userProfiles.add(      caller,      {        name;        email;      }    );    emails.add(email);  };
SKILL.md:181In the instructionsOpen original file
    // Check if the email is already used    if (emails.contains(email)) {      Runtime.trap("Email already taken");    };    // Add a user record    userProfiles.add(      caller,      {        name;        email;      }    );    emails.add(email);  };
Could it mislead the AI or hide text?Checks the skill instructions for requests to ignore you, influence the report, or hide text in invisible characters.No risks found
Could it change links or payment recipients without asking?Looks for forced referral or payment changes combined with instructions to hide the change.No risks found

Inside this skill

1 instruction sections

The Skill claims to provide calendar-event CRUD operations and send iCalendar invitations by email; it explicitly says attendee RSVP responses are not supported.

View source
SKILL.md:17In the instructionsOpen original file
This skill adds support for organising events/meetings and sending iCalendar invitations by email. It provides CRUD operations for calendar events and email-based invitation delivery.
SKILL.md:23In the instructionsOpen original file
- Internally it builds and attaches an iCalendar file to each attendees's email- This component does not yet support receiving RSVPs from attendees

The shown example requires administrator permission to create, modify, manage attendees, cancel, list, delete, or send event invitations. The ordinary user-registration endpoint does not require that permission.

View source
SKILL.md:175In the instructionsOpen original file
  public shared ({ caller }) func registerUser(name : Text, email : Text) : async () {    // Check if the user already exists
SKILL.md:197In the instructionsOpen original file
  public shared ({ caller }) func addCalendarEvent(summary : Text, description : Text, location : Text, startTimeMs : Nat64, endTimeMs : Nat64) : async () {    if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {      Runtime.trap("Unauthorized: Only admins can add calendar events");    };
SKILL.md:301In the instructionsOpen original file
  public shared ({ caller }) func sendEventInvitation(uid : Text) : async () {    if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {      Runtime.trap("Unauthorized: Only admins can send calendar event invitations");    };

Event storage and email transport are delegated to prefabricated dependencies. The supplied material only shows their interfaces and says the calendar module cannot be modified, so these lines do not establish how those dependencies handle or protect data internally.

View source
SKILL.md:28In the instructionsOpen original file
- Use the prefabricated module `mo:caffeineai-email-calendar-events/calendarEvents.mo` which cannot be modified.
SKILL.md:89In the instructionsOpen original file
- This component depends on [extension-email](../extension-email/SKILL.md) for sending calendar event emails.- Use the sendCalendarEvent function. 
Start here · InstructionsSKILL.md
extension-email-calendar-events
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.
Files and check records1 files

Coverage and gaps

Content covered in each file

These are the source ranges included in this check, not a guarantee that every issue has been resolved.

  • SKILL.mdFull text included

This report is for the version above. We read the available code and instructions without running the skill or checking extra packages it installs. This is not a promise of safety: a different version or setup may behave differently.

  • SKILL.mdInstructions

Operations mentioned in code and instructions

Connect to websites
SKILL.md:13In the instructionsOpen original file
# Email — Calendar EventsCalendar events email extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).
Lines read
348
File checksum (to compare versions)
40cdaf69b046648fd49c35345e94c30cdc38868b1977cbd80867b9a5c3bdd2a6