Skip to content

Async import of the appStore packages - #1

Open
linxia0415 wants to merge 2 commits into
mainfrom
pr-8087
Open

Async import of the appStore packages#1
linxia0415 wants to merge 2 commits into
mainfrom
pr-8087

Conversation

@linxia0415

Copy link
Copy Markdown

What does this PR do?

Async imports of all apps

@code-hawk-sit code-hawk-sit Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查摘要

  • packages/app-store/_utils/getCalendar.ts: 发现动态属性访问未校验 calendarType,存在路径遍历风险,已委托深审并确认。
  • packages/app-store/wipemycalother/lib/reschedule.ts: 发现 forEach 中使用 async 回调但未等待完成,可能导致异步操作被丢弃,已委托深审并确认。
  • 其余文件:batch 审计通过,无高危问题。

CodeHawk 提供支持 · nuwa

calendarType = calendarType.split("_other_calendar")[0];
}
const calendarApp = appStore[calendarType.split("_").join("") as keyof typeof appStore];
const calendarApp = await appStore[calendarType.split("_").join("") as keyof typeof appStore];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 AI 代码审查发现问题

📋 问题概述

在动态属性访问中,未对 calendarType 的值进行充分校验。如果 calendarType 包含恶意构造的字符串(如特殊字符或非法路径),可能导致模块加载失败、任意模块导入或执行,存在代码注入和路径遍历风险。split("_").join("") 操作也可能因输入异常导致拼接错误,引发运行时错误。

📍 问题详情

🔴 问题 1 | 严重程度: HIGH | 行号: 15

💬 详细说明:

  • 攻击者可利用此漏洞访问或执行 appStore 中的任意模块,可能导致服务器端请求伪造、远程代码执行或其他未授权操作。

📝 问题代码:

const calendarApp = await appStore[calendarType.split("_").join("") as keyof typeof appStore];

💡 修复建议:

在使用 calendarType 构造键名前,应验证其是否为预定义的有效类型之一。建议维护一个白名单列表,仅允许已知合法的 calendar 类型通过。同时,确保 appStore 中的键名与实际模块路径严格对应,避免任意字符串拼接导致的不安全访问。

✅ 修复示例:

const validCalendarTypes = new Set(['applecalendar', 'caldavcalendar', 'closecom', 'dailyvideo', 'googlecalendar', 'googlevideo', 'hubspot', 'huddle01video', 'jitsivideo', 'larkcalendar', 'office365calendar', 'office365video', 'plausible', 'salesforce', 'zohocrm', 'sendgrid', 'stripepayment', 'tandemvideo', 'vital', 'zoomvideo', 'wipemycalother', 'giphy', 'zapier', 'exchange2013calendar', 'exchange2016calendar', 'exchangecalendar', 'facetime', 'sylapsvideo']);
const normalizedType = calendarType.split('_').join('');
if (!validCalendarTypes.has(normalizedType)) {
  log.warn(`Invalid calendar type: ${calendarType}`);
  return null;
}
const calendarApp = await appStore[normalizedType as keyof typeof appStore];

🔗 参考链接

);
try {
bookingRefsFiltered.forEach((bookingRef) => {
bookingRefsFiltered.forEach(async (bookingRef) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

使用 forEach 遍历数组并执行异步操作,但 forEach 不会等待异步任务完成,导致所有异步操作被丢弃,无法捕获异常,造成资源泄漏或逻辑失败。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 125

💬 详细说明:

  • 使用 forEach 遍历数组并执行异步操作,但 forEach 不会等待异步任务完成,导致所有异步操作被丢弃,无法捕获异常,造成资源泄漏或逻辑失败。

📝 问题代码:

bookingRefsFiltered.forEach(async (bookingRef) => {

💡 修复建议:

将 forEach 替换为 for...of 循环,并在每次迭代中使用 await 等待异步操作完成,确保每个任务都被正确执行和错误处理。

✅ 修复示例:

for (const bookingRef of bookingRefsFiltered) {
  if (bookingRef.uid) {
    if (bookingRef.type.endsWith('_calendar')) {
      const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
      if (calendar) {
        await calendar.deleteEvent(bookingRef.uid, builder.calendarEvent);
      }
    } else if (bookingRef.type.endsWith('_video')) {
      await deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
    }
  }
}

🔗 参考链接

);
try {
bookingRefsFiltered.forEach((bookingRef) => {
bookingRefsFiltered.forEach(async (bookingRef) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 AI 代码审查发现问题

📋 问题概述

在 forEach 中使用 async 回调但未等待其完成,导致异步操作可能未执行完毕就继续执行后续逻辑。这可能导致日历或视频会议取消失败,且错误处理不完整(catch 块仅捕获外层异常,无法捕获内部 async 错误)。此外,若多个并发请求失败,仅记录第一个错误,其余被忽略。

📍 问题详情

🔴 问题 1 | 严重程度: HIGH | 行号: 125

💬 详细说明:

  • 日历事件可能不会被正确删除,导致数据不一致;异步操作未完成可能导致资源泄漏和竞态条件,存在安全风险。

📝 问题代码:

bookingRefsFiltered.forEach(async (bookingRef) => {

💡 修复建议:

将 forEach 替换为 for...of 遍历,并使用 await 等待每个异步操作完成;或使用 Promise.allSettled 处理所有异步任务并统一处理结果,确保所有取消操作都被正确执行和监控。

✅ 修复示例:

const promises = bookingRefsFiltered.map(async (bookingRef) => {
  if (bookingRef.uid) {
    if (bookingRef.type.endsWith("_calendar")) {
      const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
      return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent);
    } else if (bookingRef.type.endsWith("_video")) {
      return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
    }
  }
});
await Promise.allSettled(promises);

🔗 参考链接

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants