Skip to content
Report library
Purpose / Other

Extension Email Verification Skill Security Audit

What the author says it does (original text)

Support for sending an email with a link the recipient can click to prove they own the email address.

Independent security check

Security risks found

Files checked
1
Risks found
2
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.No risks found
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
Medium risk

A send failure can leave a registration record that cannot be retried

Source references: 4
What we found

The example writes the user and email mappings before awaiting the external mail send. Motoko commits preceding state at an await boundary, so a later trap in the error branch does not undo those writes. A subsequent attempt is rejected as already registered.

Why this matters

A temporary mail failure can permanently reserve the caller and address without delivering a verification link, leaving inconsistent account data and blocking registration.

The example updates users and emailToPrincipal before awaiting email delivery, then traps on a send error. Under Motoko's commit-at-await behavior, that trap does not roll back the earlier committed map updates, while a retry is rejected by the existing-user or existing-email checks. Copying this flow can therefore strand a user without a self-service retry. Users can ask for failure compensation, a separate resend endpoint, or an explicit retryable state.

SKILL.md:113In the instructionsOpen original file
  public shared ({ caller }) func registerUser(email : Text, name : Text) : async () {    if (users.containsKey(caller)) {      Runtime.trap("User already registered");    };    if (emailToPrincipal.containsKey(email)) {      Runtime.trap("Email already registered");    };
Show 3 other places
SKILL.md:124In the instructionsOpen original file
    };    users.add(caller, user);    emailToPrincipal.add(email, caller);    let result = await EmailClient.sendVerificationEmail(      "no-reply",      [email],      "Welcome to Our Service",      "Hello " # name # ",<br><br>Thank you for registering with our service. Please <a href=\"{{VERIFICATION_URL}}\">click here</a> to verify your email address<br><br>Best regards,<br>The Team",    );
SKILL.md:133In the instructionsOpen original file
    switch (result) {      case (#ok) {};      case (#err(error)) {        Runtime.trap("Couldn't send verification email: " # error);      };    };  };
SKILL.md:112In the instructionsOpen original file
  public shared ({ caller }) func registerUser(email : Text, name : Text) : async () {    if (users.containsKey(caller)) {      Runtime.trap("User already registered");    };    if (emailToPrincipal.containsKey(email)) {      Runtime.trap("Email already registered");    };
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.No risks found
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.Risks found: 1
Medium risk

The example public endpoint can send attacker-influenced HTML to arbitrary addresses

Source references: 2
What we found

The example exposes registerUser as a public shared function, accepts the recipient and name from its caller, and concatenates name directly into an HTML email sent under the service's identity. A caller can place links or other HTML in name so a third party receives misleading service-branded content.

Why this matters

If adopted directly, the mail channel could be used for phishing or spam, harming sender-domain reputation and potentially causing delivery costs or provider suspension.

This is copyable example code, not proof of a deployed endpoint, but it demonstrates the stated risk: a public registration function accepts caller-supplied email and name, inserts name into HTML without escaping, and sends from a fixed no-reply identity. If adopted as shown, a caller could send branded mail containing attacker-controlled HTML to any unregistered address, enabling deception or phishing; no rate limit is shown. Users can ask for HTML escaping, rate limits, and recipient-abuse controls.

SKILL.md:112In the instructionsOpen original file
  public shared ({ caller }) func registerUser(email : Text, name : Text) : async () {    if (users.containsKey(caller)) {      Runtime.trap("User already registered");    };    if (emailToPrincipal.containsKey(email)) {      Runtime.trap("Email already registered");    };
Show 1 other places
SKILL.md:126In the instructionsOpen original file
    emailToPrincipal.add(email, caller);    let result = await EmailClient.sendVerificationEmail(      "no-reply",      [email],      "Welcome to Our Service",      "Hello " # name # ",<br><br>Thank you for registering with our service. Please <a href=\"{{VERIFICATION_URL}}\">click here</a> to verify your email address<br><br>Best regards,<br>The Team",    );

Inside this skill

2 instruction sections

The Skill is intended to email a recipient-specific verification link and record verified addresses in a shared set; it explicitly directs applications to query that set instead of maintaining a separate profile flag.

View source
SKILL.md:17In the instructionsOpen original file
This skill adds email address verification via a click-to-verify link. The `MixinEmailVerification` handles the verification callback; `verifiedEmails` tracks verified addresses.
SKILL.md:47In the instructionsOpen original file
To check whether an email is verified use the `contains` function. Do NOT try to track the email verification status independently by storing it against the user profile.
SKILL.md:64In the instructionsOpen original file
- It returns a SendResult which is #ok if the email is sent successfully otherwise #err(error) with the error text. - Each recipient receives an individual email with a specific verification link for them- The htmlBody MUST contain the placeholder text {{VERIFICATION_URL}}

The core verification callback and verified-address storage reside in prefabricated dependencies marked as unmodifiable. The supplied source shows only their interfaces, so these materials do not establish token expiry, replay protection, or how links are bound to addresses.

View source
SKILL.md:25In the instructionsOpen original file
Use the prefabricated module `mo:caffeineai-email-verification/verifiedEmails.mo` which cannot be modified.
SKILL.md:39In the instructionsOpen original file
  public func contains(state : State, email : Text) : Bool;  public func iter(state : State) : Iter.Iter<Text>;  public func size(state : State) : Nat;};
SKILL.md:51In the instructionsOpen original file
Use the prefabricated module `mo:caffeineai-email-verification/verificationMixin.mo` which cannot be modified.The MixinEmailVerification handles calls to the verification link to verify an email address.
Start here · InstructionsSKILL.md
extension-email-verification
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 — VerificationEmail verification extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).
Lines read
179
File checksum (to compare versions)
65158a61208ebd2d3490e1306bce7cffdd3505d1178575e5bb155122d363b46d