import { createServer } from 'node:http' import { readFile, mkdir, writeFile } from 'node:fs/promises' import { fileURLToPath } from 'node:url' import path from 'node:path' const root = fileURLToPath(new URL('../../', import.meta.url)) const directory = path.join(root, 'test-log', `review-plugin-browser-${Date.now()}`) await mkdir(directory, { recursive: true }) const page = await readFile(path.join(root, 'plugins/pmail_telegram_push/src/App.vue'), 'utf8') const container = await readFile(path.join(root, 'frontend/src/views/components/PluginSettings/PluginSettings.vue'), 'utf8') const headers = await readFile(path.join(root, 'backend/listen/http_server/https_server.go'), 'utf8') const mounted = page.match(/onMounted\(\(\) => \{([\s\S]*?)\n\}\)/)?.[1] const sandbox = container.match(/sandbox="([^"]+)"/)?.[1] const policy = headers.match(/"Content-Security-Policy", "([^"]*connect-src 'none'[^"]*)"/)?.[1] if (!mounted || !sandbox || !policy) throw new Error('未找到被审查的真实模板、安全策略或挂载函数') // 浏览器隔离夹具:使用源码中的挂载函数、sandbox 和 CSP,不访问业务服务或数据库。 const events = [] const send = (response, type, body) => { response.setHeader('Content-Type', type) response.setHeader('Cache-Control', 'no-store') response.end(body) } const server = createServer((request, response) => { if (request.url === '/health') return send(response, 'application/json', JSON.stringify({ ready: true, events })) if (request.url === '/api/audit') { events.push('api-request') return send(response, 'application/json', '{"errorNo":0}') } if (request.url === '/frame') { response.setHeader('Content-Security-Policy', policy) return send(response, 'text/html; charset=utf-8', ``) } send(response, 'text/html; charset=utf-8', `Smail 插件隔离审查

Smail 插件隔离审查

不连接业务数据库,不发送第三方消息。


    `)
})
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
const state = { url: `http://127.0.0.1:${server.address().port}`, sandbox, policy }
await writeFile(path.join(directory, 'state.json'), JSON.stringify(state, null, 2) + '\n')
console.log(JSON.stringify({ ...state, directory: path.relative(root, directory) }))
const stop = () => { server.close(); server.closeAllConnections() }
process.once('SIGINT', stop)
process.once('SIGTERM', stop)