背景与价值CSV注入可在表格软件中触发公式执行与外连。统一转义策略与长度限制可有效阻断风险并保证导出可用性。统一规范公式转义:以 `'` 前缀转义以 `=,+,-,@` 开头的单元格内容。长度限制:对单元格设置最大长度并拒绝超限或截断。字段白名单:仅导出允许字段并统一顺序与类型。核心实现转义与限制function needsEscape(s: string): boolean { return /^[=+\-@]/.test(s) } function escapeCell(s: string, maxLen = 1024): string { let v = s if (needsEscape(v)) v = "'" + v if (v.length > maxLen) v = v.slice(0, maxLen) return v.replace(/[\r\n]/g, ' ') } function toCsvRow(fields: string[], obj: Record<string, any>): string { const cells = fields.map(f => escapeCell(String(obj[f] ?? ''))) return cells.map(c => '"' + c.replace(/"/g,'""') + '"').join(',') } 字段白名单与导出const allowFields = ['id','name','email','phone'] function validEmail(s: string): boolean { return /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(s) } function validPhone(s: string): boolean { return /^[0-9\-+]{6,20}$/.test(s) } function normalize(obj: Record<string, any>): Record<string, any> { const out: Record<string, any> = {} out.id = String(obj.id ?? '') out.name = String(obj.name ?? '') out.email = validEmail(String(obj.email ?? '')) ? String(obj.email) : '' out.phone = validPhone(String(obj.phone ?? '')) ? String(obj.phone) : '' return out } function exportCsv(rows: Record<string, any>[]): string { const header = allowFields.map(f => '"' + f + '"').join(',') const lines = [header] for (const r of rows) { const n = normalize(r) lines.push(toCsvRow(allowFields, n)) } return lines.join('\n') } 落地建议在后台导出路径统一执行公式转义与长度限制,拒绝超限或非法值。以白名单驱动导出字段,统一顺序与类型并执行基础校验。对换行与引号统一转义,保证CSV在各表格软件中可用。验证清单是否对以 `=,+,-,@` 开头的内容进行了前缀转义。单元格是否限制最大长度,换行与引号是否统一转义。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
3.480837s