



























11// Qqbot tests cover trusted outbound media-path root resolution.
2+import { randomUUID } from "node:crypto";
23import fs from "node:fs";
34import os from "node:os";
45import path from "node:path";
@@ -13,7 +14,7 @@ afterEach(() => {
1314while (cleanupPaths.length > 0) {
1415const target = cleanupPaths.pop();
1516if (target) {
16-fs.rmSync(target, { recursive: true, force: true });
17+fs.rmSync(target, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
1718}
1819}
1920});
@@ -22,22 +23,27 @@ function makeTtsStyleVoiceFile(): string {
2223// Mirrors cron auto-TTS: speech-core writes the voice file under the preferred
2324// OpenClaw temp root, which is outside the QQ Bot media storage tree.
2425const tmpRoot = resolvePreferredOpenClawTmpDir();
25-const ttsDir = fs.mkdtempSync(path.join(tmpRoot, "tts-"));
26-cleanupPaths.push(ttsDir);
26+const ttsDir = makeTrackedDir(tmpRoot, "tts-");
2727const voicePath = path.join(ttsDir, "voice-123.mp3");
2828fs.writeFileSync(voicePath, "audio");
2929return voicePath;
3030}
313132+function makeTrackedDir(parentDir: string, prefix: string): string {
33+const dir = path.join(parentDir, `${prefix}${randomUUID()}`);
34+fs.mkdirSync(dir);
35+cleanupPaths.push(dir);
36+return dir;
37+}
38+3239describe("resolveTrustedOutboundMediaPath", () => {
3340it("trusts framework media under OpenClaw's hardened temp root", () => {
3441const voicePath = makeTtsStyleVoiceFile();
3542expect(resolveTrustedOutboundMediaPath(voicePath)).toBe(fs.realpathSync(voicePath));
3643});
37443845it("rejects local media outside every trusted root", () => {
39-const outsideDir = fs.mkdtempSync(path.join(os.tmpdir(), "qq-out-of-root-"));
40-cleanupPaths.push(outsideDir);
46+const outsideDir = makeTrackedDir(os.tmpdir(), "qq-out-of-root-");
4147const strayPath = path.join(outsideDir, "stray.mp3");
4248fs.writeFileSync(strayPath, "audio");
4349@@ -46,8 +52,7 @@ describe("resolveTrustedOutboundMediaPath", () => {
46524753it("accepts a not-yet-flushed temp file only when allowMissing is set", () => {
4854const tmpRoot = resolvePreferredOpenClawTmpDir();
49-const ttsDir = fs.mkdtempSync(path.join(tmpRoot, "tts-pending-"));
50-cleanupPaths.push(ttsDir);
55+const ttsDir = makeTrackedDir(tmpRoot, "tts-pending-");
5156const pendingPath = path.join(ttsDir, "voice-pending.mp3");
52575358expect(resolveTrustedOutboundMediaPath(pendingPath)).toBeNull();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。