---

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在各表格软件中可用。

验证清单

  • 是否对以 =,+,-,@ 开头的内容进行了前缀转义。
  • 单元格是否限制最大长度,换行与引号是否统一转义。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部