openclaw-quiubo 2.6.25 → 2.6.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -323,6 +323,23 @@ src/
323
323
  | OpenClaw | `sendOpenclawResponse()` |
324
324
  | Webhooks | `configureWebhook()` |
325
325
 
326
+ ## Known Security Scanner Warnings
327
+
328
+ When installing, OpenClaw's plugin scanner may flag two patterns. Both are false positives:
329
+
330
+ - **"Shell command execution detected (child_process)"** — From `pusher-js`'s bundled XMLHttpRequest polyfill. This sync code path is never executed by the plugin.
331
+ - **"Environment variable access combined with network send"** — The plugin reads `process.env.HOME` to locate `~/.openclaw/cron/` for persisting cursors and keys. No credentials flow through environment variables.
332
+
333
+ To suppress the auto-load warning, add the plugin to your allowlist in `~/.openclaw/openclaw.json`:
334
+
335
+ ```json
336
+ {
337
+ "plugins": {
338
+ "allow": ["openclaw-quiubo"]
339
+ }
340
+ }
341
+ ```
342
+
326
343
  ## License
327
344
 
328
345
  MIT
package/dist/index.js CHANGED
@@ -12882,7 +12882,8 @@ var RealtimeGateway = class {
12882
12882
  senderIdentityId: data.senderId,
12883
12883
  senderUsername: data.senderUsername,
12884
12884
  plaintext: data.plaintext,
12885
- createdAt: data.createdAt
12885
+ createdAt: data.createdAt,
12886
+ ...data.attachments?.length ? { attachments: data.attachments } : {}
12886
12887
  })).catch((err) => {
12887
12888
  log.error?.(`Failed to route Pusher message ${data.messageId}: ${err}`);
12888
12889
  });
@@ -12912,7 +12913,8 @@ var RealtimeGateway = class {
12912
12913
  senderIdentityId: data.senderId,
12913
12914
  senderUsername: data.senderUsername,
12914
12915
  plaintext,
12915
- createdAt: data.createdAt
12916
+ createdAt: data.createdAt,
12917
+ ...data.attachments?.length ? { attachments: data.attachments } : {}
12916
12918
  }));
12917
12919
  } catch (decErr) {
12918
12920
  log.error?.(`[e2ee:pusher] Decryption failed for message ${data.messageId} in group ${data.groupId}: ${decErr}`);
@@ -12968,7 +12970,8 @@ var RealtimeGateway = class {
12968
12970
  groupId,
12969
12971
  senderIdentityId: msg.senderIdentityId,
12970
12972
  plaintext: msg.plaintext,
12971
- createdAt: msg.createdAt
12973
+ createdAt: msg.createdAt,
12974
+ ...msg.attachments?.length ? { attachments: msg.attachments } : {}
12972
12975
  });
12973
12976
  } catch (error) {
12974
12977
  this.log.error?.(`Failed to fetch message ${messageId}:`, error);
@@ -13156,7 +13159,8 @@ var RealtimeGateway = class {
13156
13159
  groupId,
13157
13160
  senderIdentityId: msg.senderIdentityId,
13158
13161
  plaintext,
13159
- createdAt: msg.createdAt
13162
+ createdAt: msg.createdAt,
13163
+ ...msg.attachments?.length ? { attachments: msg.attachments } : {}
13160
13164
  });
13161
13165
  } catch (error) {
13162
13166
  this.log.error?.(`Failed to handle message ${msg.id}:`, error);
@@ -14228,8 +14232,29 @@ async function routeInboundMessage(opts) {
14228
14232
  const imageAttachments = (msg.attachments ?? []).filter(
14229
14233
  (att) => att.storageUrl && att.mimeType?.startsWith("image/")
14230
14234
  );
14231
- const mediaUrls = imageAttachments.map((att) => att.storageUrl);
14232
- const mediaTypes = imageAttachments.map((att) => att.mimeType);
14235
+ const mediaPaths = [];
14236
+ const mediaTypes = [];
14237
+ if (imageAttachments.length > 0) {
14238
+ const mediaDir = join2(process.env.HOME ?? process.env.USERPROFILE ?? "", ".openclaw", "media", "inbound");
14239
+ await mkdir2(mediaDir, { recursive: true });
14240
+ for (const att of imageAttachments) {
14241
+ try {
14242
+ const resp = await fetch(att.storageUrl);
14243
+ if (!resp.ok) {
14244
+ log?.warn?.(`[${accountId}] Failed to download attachment ${att.filename}: ${resp.status}`);
14245
+ continue;
14246
+ }
14247
+ const buffer = Buffer.from(await resp.arrayBuffer());
14248
+ const ext = att.filename?.split(".").pop() || "png";
14249
+ const localPath = join2(mediaDir, `${msg.messageId}-${mediaPaths.length}.${ext}`);
14250
+ await writeFile2(localPath, buffer);
14251
+ mediaPaths.push(localPath);
14252
+ mediaTypes.push(att.mimeType);
14253
+ } catch (err) {
14254
+ log?.warn?.(`[${accountId}] Failed to download attachment ${att.filename}: ${err}`);
14255
+ }
14256
+ }
14257
+ }
14233
14258
  if (msg.attachments?.length) {
14234
14259
  for (const att of msg.attachments) {
14235
14260
  if (att.storageUrl && att.mimeType?.startsWith("image/")) continue;
@@ -14239,7 +14264,7 @@ async function routeInboundMessage(opts) {
14239
14264
  [Attached: ${att.filename}${sizeKb ? `, ${sizeKb}` : ""}]`;
14240
14265
  }
14241
14266
  }
14242
- log?.info?.(`[${accountId}] Quiubo: inbound from ${senderId} in group ${groupId}: ${text?.slice(0, 100)}`);
14267
+ log?.info?.(`[${accountId}] Quiubo: inbound from ${senderId} in group ${groupId}: ${text?.slice(0, 100)}${mediaPaths.length > 0 ? ` [${mediaPaths.length} image(s)]` : ""}`);
14243
14268
  const sendTyping = async () => {
14244
14269
  try {
14245
14270
  await client.sendTypingIndicator(groupId, botIdentityId);
@@ -14270,8 +14295,11 @@ async function routeInboundMessage(opts) {
14270
14295
  Surface: CHANNEL_ID,
14271
14296
  MessageSid: `quiubo-${msg.messageId}`,
14272
14297
  Timestamp: msg.createdAt ? new Date(msg.createdAt).getTime() : Date.now(),
14273
- ...mediaUrls.length > 0 && {
14274
- MediaUrls: mediaUrls,
14298
+ ...mediaPaths.length > 0 && {
14299
+ MediaPath: mediaPaths[0],
14300
+ MediaUrl: mediaPaths[0],
14301
+ MediaPaths: mediaPaths,
14302
+ MediaUrls: mediaPaths,
14275
14303
  MediaTypes: mediaTypes
14276
14304
  }
14277
14305
  });