Files
dsh_shenxian/scripts/verify-inject.cjs
T

63 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* verify-inject.cjs —— 注入脚本校验(**档案 81 · R1 起改为校验独立文件**)
*
* 历史(2026-09-13 事故):注入脚本原先是 `proxy.ts` 里的 **TS 模板字面量**,里面的 `\n` 会在
* 模板求值时先被转义 ⇒ 注入浏览器的那段 JS 变 SyntaxError ⇒ **整段脚本静默不执行**(浮层/自愈/助手全废)。
* 当时"校验"只抽原始文本跑 new Function,**跳过了求值** ⇒ 假绿。
*
* 现在(R1):脚本已外置到 `assets/inject/*.js`(纯 JS),本脚本负责:
* ① 断言这些文件存在、非空、且能通过 `node --check`(等价于浏览器解析);
* ② 断言 `src/supervisor/proxy.ts` **不再**把注入脚本内联成模板字面量(防回退);
* ③ 断言运行时串里不含 `<script` / `</script>`(会提前结束注入的 script 标签)。
*
* 用法:node scripts/verify-inject.cjs 退出码 0=合格 / 1=不合格
*/
const fs = require('fs')
const os = require('os')
const path = require('path')
const cp = require('child_process')
const ROOT = path.join(__dirname, '..')
const DIR = path.join(ROOT, 'assets', 'inject')
const PROXY_SRC = path.join(ROOT, 'src', 'supervisor', 'proxy.ts')
let bad = 0
const files = fs.existsSync(DIR) ? fs.readdirSync(DIR).filter((f) => f.endsWith('.js')) : []
console.log('=== 注入脚本(' + DIR + ',' + files.length + ' 个)===')
if (files.length === 0) { console.log(' ✗ assets/inject 下没有 .js(档案 81 R1 要求注入脚本外置)'); bad++ }
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'vinj-'))
for (const f of files) {
const abs = path.join(DIR, f)
const code = fs.readFileSync(abs, 'utf8')
if (code.trim().length < 100) { console.log(' ✗ ' + f + ':内容过短,疑似被清空'); bad++; continue }
const t = path.join(tmp, f)
fs.writeFileSync(t, code)
const r = cp.spawnSync(process.execPath, ['--check', t], { encoding: 'utf8' })
if (r.status !== 0) {
console.log(' ✗ ' + f + ':**语法失败**(浏览器里会静默失效)→ ' + String(r.stderr || '').split('\n').slice(0, 2).join(' '))
bad++
} else {
const danger = ['</script', '<script'].filter((k) => code.includes(k))
if (danger.length) { console.log(' ✗ ' + f + ':含 ' + danger.join('/') + '(会提前结束注入的 script 标签)'); bad++ }
else console.log(' ✓ ' + f + ' 语法通过(' + code.length + ' 字符)')
}
}
fs.rmSync(tmp, { recursive: true, force: true })
// 防回退:proxy.ts 不得再内联注入脚本
if (fs.existsSync(PROXY_SRC)) {
const src = fs.readFileSync(PROXY_SRC, 'utf8')
const inlined = /const SESSION_[A-Z_]+ = `/g.test(src)
if (inlined) { console.log(' ✗ proxy.ts 仍把注入脚本内联成模板字面量(应改为 loadInject 读 assets/inject)'); bad++ }
else {
const loads = (src.match(/loadInject\('([^']+)'\)/g) || []).length
console.log(' ✓ proxy.ts 已走 loadInject(' + loads + ' 处)')
if (loads < files.length) { console.log(' ⚠️ loadInject 处数(' + loads + ') < 文件数(' + files.length + '),确认是否漏用'); }
}
}
console.log(bad ? '结论:' + bad + ' 项不合格 ❌ —— 别推上线' : '结论:全部合格 ✅')
process.exit(bad ? 1 : 0)