跳转到正文
报告库
用途分类 / 其他用途

Extension Email Verification Skill 安全审计

作者说它能做什么(原文)

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

第三方安全检查结论

发现安全风险

已检查文件
1
发现的风险
2
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。未发现风险
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。发现 1 项风险
中风险

发送失败可能留下不可重试的已注册记录

原文依据:4 处
发现了什么

示例先写入用户和邮箱映射,再等待外部邮件发送。Motoko 在 await 边界提交此前状态;如果发送随后返回错误,错误分支的 trap 不会撤销 await 前的写入。下一次调用又会因“用户或邮箱已注册”而被拒绝。

为什么需要注意

临时邮件故障可能永久占用该调用者和邮箱的注册位置,但用户从未收到验证链接,造成账户数据不一致和注册阻断。

示例在邮件发送前写入 users 和 emailToPrincipal,然后跨越 await;发送失败后执行 trap。按 Motoko 的 await 提交边界,这个 trap 不会回滚此前已提交的映射更新,而重试会被“用户已注册”或“邮箱已注册”检查拒绝。因此照搬示例可能使用户无法自行重试验证邮件。用户可要求作者提供失败补偿、独立重发端点或在持久状态中明确记录可重试状态。

SKILL.md:113来自说明文档打开原文件
  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");    };
查看另外 3 个位置
SKILL.md:124来自说明文档打开原文件
    };    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:133来自说明文档打开原文件
    switch (result) {      case (#ok) {};      case (#err(error)) {        Runtime.trap("Couldn't send verification email: " # error);      };    };  };
SKILL.md:112来自说明文档打开原文件
  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");    };
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。未发现风险
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。未发现风险
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。未发现风险
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。发现 1 项风险
中风险

示例公共端点可向任意地址发送含未转义用户 HTML 的邮件

原文依据:2 处
发现了什么

示例把 registerUser 暴露为公共共享函数,由调用者提供收件地址和 name;随后将 name 直接拼接进 HTML,并以服务方身份发送。攻击者可在 name 中加入链接或其他 HTML,使第三方收到看似由该服务发送的误导内容。

为什么需要注意

若应用直接采用该示例,邮件渠道可能被用于钓鱼或垃圾邮件,损害发件域名信誉,并可能产生投递成本或封禁风险。

这是可复制的示例,而非已部署代码,但它确实展示了风险:公共注册端点接受调用者提供的 email 和 name,并把 name 未经 HTML 转义直接拼入验证邮件,再以固定的 no-reply 身份发送。若应用照搬,调用者可让任意未注册地址收到带攻击者控制 HTML 的品牌邮件,用于误导或钓鱼;源码也未展示速率限制。用户可要求作者加入 HTML 转义、发送频率限制及收件人滥用防护。

SKILL.md:112来自说明文档打开原文件
  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");    };
查看另外 1 个位置
SKILL.md:126来自说明文档打开原文件
    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 逻辑拆解

2 个说明模块

该 Skill 的目标是通过唯一验证链接发送邮件,并以共享的邮箱集合记录验证状态;它明确要求应用查询该集合,不要在用户资料中另建验证标记。

查看原文
SKILL.md:17来自说明文档打开原文件
This skill adds email address verification via a click-to-verify link. The `MixinEmailVerification` handles the verification callback; `verifiedEmails` tracks verified addresses.
SKILL.md:47来自说明文档打开原文件
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:64来自说明文档打开原文件
- 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}}

验证回调和已验证邮箱存储的核心逻辑位于标为不可修改的预制依赖中;所提供源码只展示接口,因此无法从这些材料判断令牌有效期、重放防护或链接与邮箱的绑定方式。

查看原文
SKILL.md:25来自说明文档打开原文件
Use the prefabricated module `mo:caffeineai-email-verification/verifiedEmails.mo` which cannot be modified.
SKILL.md:39来自说明文档打开原文件
  public func contains(state : State, email : Text) : Bool;  public func iter(state : State) : Iter.Iter<Text>;  public func size(state : State) : Nat;};
SKILL.md:51来自说明文档打开原文件
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.
从这里开始 · 工作说明SKILL.md
extension-email-verification
连线表示工作说明包含的模块,不是实际运行顺序。点击模块可查看原文。
文件与检查记录1 个文件

检查范围与遗漏

逐文件查看涉及的内容

下方列出本次涉及的原文范围;纳入检查不代表已查清所有问题。

  • SKILL.md已纳入全文

这份报告只针对上方版本。我们看了拿到的代码和说明文件,没有实际运行 Skill,也没有检查它另外安装的软件包。因此,这不是“保证安全”的承诺;换了版本或使用环境,结果也可能不同。

  • SKILL.md工作说明

代码和说明中提到的操作

连接外部网站
SKILL.md:13来自说明文档打开原文件
# Email — VerificationEmail verification extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).
读取了多少行
179
文件校验值(用于核对版本)
65158a61208ebd2d3490e1306bce7cffdd3505d1178575e5bb155122d363b46d