---
title: CSV注入防护与数据导出治理(公式转义/长度限制)最佳实践
keywords:
- CSV注入
- 公式转义
- Excel
- 长度限制
- 字段白名单
- 逗号分隔
description: 通过导出前公式转义与长度限制、字段白名单与统一编码,系统性防止CSV注入导致的命令执行与数据泄露风险。
categories:
- 文章资讯
- 编程技术
---
背景与价值
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在各表格软件中可用。
验证清单
- 是否对以
=,+,-,@开头的内容进行了前缀转义。 - 单元格是否限制最大长度,换行与引号是否统一转义。

发表评论 取消回复