chore(scripts): 侧车导出加固——site-id UUID 校验与 audit 非 CDATA 匹配
评审两条非阻塞加固:--site-id 拼入 SQL 前过 UUID 形态白名单(非 UUID 拒绝并 明确报错);--audit 的 attachment_url 抽取正则同时匹配 CDATA 与裸文本两形态。 对真实数据重跑数字不变(859 条 / 855 对 836 命中,输出哈希一致)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,14 @@ const DEFAULT_CONTAINER = 'infrastructure-postgres-1'
|
|||||||
const DEFAULT_USER = 'cms'
|
const DEFAULT_USER = 'cms'
|
||||||
const DEFAULT_DB = 'cms'
|
const DEFAULT_DB = 'cms'
|
||||||
|
|
||||||
/** 唯一一条对 cms 执行的 SQL(只读 SELECT;source_url IS NOT NULL——867 中 8 行 NULL 不带出) */
|
/** site-id 白名单校验:UUID 形态(评审加固)——SQL 里 site_id 以字面量内插,非 UUID 输入在拼 SQL 前拒绝 */
|
||||||
|
function assertValidSiteId(siteId) {
|
||||||
|
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(siteId)) {
|
||||||
|
throw new Error(`--site-id 不是合法 UUID(36 位形态):${siteId}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 唯一一条对 cms 执行的 SQL(只读 SELECT;site_id 已过 UUID 校验;source_url IS NOT NULL——867 中 8 行 NULL 不带出) */
|
||||||
function exportSql(siteId) {
|
function exportSql(siteId) {
|
||||||
return (
|
return (
|
||||||
`SELECT source_url, file_path FROM media_assets ` +
|
`SELECT source_url, file_path FROM media_assets ` +
|
||||||
@@ -90,9 +97,10 @@ async function auditAgainstWxr(mapPath, wxrPath) {
|
|||||||
const sidecarByExact = new Set(map.map((e) => e.sourceUrl))
|
const sidecarByExact = new Set(map.map((e) => e.sourceUrl))
|
||||||
const sidecarByNormalized = new Set(map.map((e) => normalizeUrl(e.sourceUrl)))
|
const sidecarByNormalized = new Set(map.map((e) => normalizeUrl(e.sourceUrl)))
|
||||||
const wxr = await readFile(wxrPath, 'utf8')
|
const wxr = await readFile(wxrPath, 'utf8')
|
||||||
const attachmentUrls = [...wxr.matchAll(/<wp:attachment_url><!\[CDATA\[([^\]]*)\]\]><\/wp:attachment_url>/g)].map(
|
// CDATA 与裸文本两种形态都匹配(评审加固:WXR 导出器未必总包 CDATA);分支互斥,m[1] ?? m[2]
|
||||||
(m) => m[1],
|
const attachmentUrls = [
|
||||||
)
|
...wxr.matchAll(/<wp:attachment_url>(?:<!\[CDATA\[([^\]]*)\]\]>|([^<]*))<\/wp:attachment_url>/g),
|
||||||
|
].map((m) => m[1] ?? m[2] ?? '')
|
||||||
const seen = new Set()
|
const seen = new Set()
|
||||||
const hitsExact = [] // 归一前即完全相等
|
const hitsExact = [] // 归一前即完全相等
|
||||||
const hitsNormalized = [] // 仅归一后相等(大小写/尾斜杠救回)
|
const hitsNormalized = [] // 仅归一后相等(大小写/尾斜杠救回)
|
||||||
@@ -156,6 +164,7 @@ function parseArgs(argv) {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const args = parseArgs(process.argv.slice(2))
|
const args = parseArgs(process.argv.slice(2))
|
||||||
|
assertValidSiteId(args.siteId)
|
||||||
const sql = exportSql(args.siteId)
|
const sql = exportSql(args.siteId)
|
||||||
|
|
||||||
process.stderr.write(`[export-media-map] 只读查询:docker exec ${args.container} psql -U ${args.user} -d ${args.db}\n`)
|
process.stderr.write(`[export-media-map] 只读查询:docker exec ${args.container} psql -U ${args.user} -d ${args.db}\n`)
|
||||||
|
|||||||
Reference in New Issue
Block a user