fix(wechat): enforce current-turn image paths in page delivery
Memind CI / Test, build, and release guards (push) Successful in 6m58s
Memind CI / Test, build, and release guards (push) Successful in 6m58s
Materialize wechat-mp uploads into dated public/images paths during vision preprocessing and fail closed when delivered HTML references stale workspace images instead of the current turn allowlist. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
buildAllowedPageImageEmbedKeys,
|
||||
extractHtmlImageSourceKeys,
|
||||
materializeWechatPublicImageForEmbed,
|
||||
verifyHtmlImageSourcesAllowed,
|
||||
} from './chat-image-materialize.mjs';
|
||||
|
||||
test('materializeWechatPublicImageForEmbed copies wechat-mp images into public/images date dir', (t) => {
|
||||
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'chat-image-materialize-'));
|
||||
t.after(() => fs.rmSync(publishDir, { recursive: true, force: true }));
|
||||
const sourceRel = 'public/wechat-mp/sample-photo.jpg';
|
||||
const sourceAbs = path.join(publishDir, sourceRel);
|
||||
fs.mkdirSync(path.dirname(sourceAbs), { recursive: true });
|
||||
fs.writeFileSync(sourceAbs, Buffer.from('fresh-image-bytes'));
|
||||
|
||||
const result = materializeWechatPublicImageForEmbed({
|
||||
publishDir,
|
||||
rawUrl: 'https://m.tkmind.cn/MindSpace/user-1/public/wechat-mp/sample-photo.jpg',
|
||||
now: new Date('2026-08-27T04:00:00.000Z'),
|
||||
});
|
||||
|
||||
assert.ok(result?.materialized);
|
||||
assert.match(result.relativeEmbedPath, /^images\/2026-08-27\/[a-f0-9]{8}-sample-photo\.jpg$/);
|
||||
assert.equal(fs.existsSync(path.join(publishDir, result.publicRelativePath)), true);
|
||||
});
|
||||
|
||||
test('verifyHtmlImageSourcesAllowed rejects stale workspace images for the current turn', () => {
|
||||
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'chat-image-verify-'));
|
||||
const sourceAbs = path.join(publishDir, 'public/wechat-mp/new.jpg');
|
||||
fs.mkdirSync(path.dirname(sourceAbs), { recursive: true });
|
||||
fs.writeFileSync(sourceAbs, Buffer.from('new-turn-image'));
|
||||
const allowed = buildAllowedPageImageEmbedKeys({
|
||||
publishDir,
|
||||
imageUrls: ['https://m.tkmind.cn/MindSpace/user-1/public/wechat-mp/new.jpg'],
|
||||
});
|
||||
const html = [
|
||||
'<html><body>',
|
||||
'<img src="images/2026-08-22/old-photo.jpg" alt="old">',
|
||||
'</body></html>',
|
||||
].join('');
|
||||
const verification = verifyHtmlImageSourcesAllowed(html, allowed);
|
||||
assert.equal(verification.ok, false);
|
||||
assert.equal(verification.reason, 'stale_image_source');
|
||||
fs.rmSync(publishDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
test('verifyHtmlImageSourcesAllowed accepts materialized current-turn image paths', () => {
|
||||
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'chat-image-verify-ok-'));
|
||||
const sourceAbs = path.join(publishDir, 'public/wechat-mp/new.jpg');
|
||||
fs.mkdirSync(path.dirname(sourceAbs), { recursive: true });
|
||||
fs.writeFileSync(sourceAbs, Buffer.from('new-turn-image'));
|
||||
const materialized = materializeWechatPublicImageForEmbed({
|
||||
publishDir,
|
||||
rawUrl: 'https://m.tkmind.cn/MindSpace/user-1/public/wechat-mp/new.jpg',
|
||||
now: new Date('2026-08-27T04:00:00.000Z'),
|
||||
});
|
||||
const allowed = buildAllowedPageImageEmbedKeys({
|
||||
publishDir,
|
||||
imageUrls: ['https://m.tkmind.cn/MindSpace/user-1/public/wechat-mp/new.jpg'],
|
||||
});
|
||||
const html = `<html><body><img src="${materialized.relativeEmbedPath}" alt="new"></body></html>`;
|
||||
const keys = extractHtmlImageSourceKeys(html);
|
||||
assert.equal(verifyHtmlImageSourcesAllowed(html, allowed).ok, true);
|
||||
assert.ok(keys.size > 0);
|
||||
fs.rmSync(publishDir, { recursive: true, force: true });
|
||||
});
|
||||
Reference in New Issue
Block a user