CSV 导出前先做公式注入审计:一个零依赖 Python 检查器

举报
yd_299903619 发表于 2026/11/04 08:04:12 2026/11/04
【摘要】 介绍一个只读 CSV 公式注入审计器:识别公式前缀、隐藏字符和数值型正负号,输出行列位置与内容预览,并包含 4 项实际通过的单元测试。

CSV 看似只是纯文本,但用户把它拖进 Excel、WPS 或其他电子表格后,以 =、+、-、@ 开头的单元格可能被当作公式解释。用户提交的昵称、备注、地址或外部导入数据一旦带有这些前缀,就可能形成公式注入风险。

本文验证一个只读检查器:它不修改原 CSV,只定位可疑单元格,输出行号、列号、前缀类别和内容预览,让数据导出流程能够在发布文件前做一次显式审核。

边界与原则

这个工具负责“发现”,不负责自动清洗。原因是 -12.5、+100 这类内容也可能有真实业务含义,直接改写会改变数据。工具将它们标记为 formula_prefix_numeric,由数据所有者决定加单引号、转成数值列,还是在导出格式层做安全编码。

检查范围:

  • =、+、-、@ 开头的内容;
  • 忽略前导空白后命中的内容;
  • 制表符、回车等不可见前缀;
  • 保留原始行号、列号和短预览。

为什么不能只检查第一个字节

电子表格可能忽略前导空格。因此仅判断 value[0] 会漏掉 " @SUM(A1:A2)"。实现先执行 lstrip(),再判断首个有效字符;同时把原始预览保留下来,便于定位真实字段。

def classify_cell(value):
    stripped = value.lstrip()
    if not stripped:
        return None
    if stripped[0] in ("=", "+", "-", "@", "\t", "\r"):
        if stripped[0] in "+-" and _looks_numeric(stripped):
            return "formula_prefix_numeric"
        return "formula_prefix"
    return None

_looks_numeric 使用 float() 尝试解析。它不是为了判断“安全”,而是为了区分“像数字的正负号”和明显的公式前缀,帮助处理人员做更精准的决策。

使用标准库读取 CSV

csv.reader 会处理引号、逗号和跨行字段,避免用字符串 split(',') 时常见的错列问题。文件使用 utf-8-sig 打开,可以同时兼容带 BOM 和不带 BOM 的输入。

with path.open("r", encoding="utf-8-sig", newline="") as handle:
    rows = list(csv.reader(handle))

检查器只读输入文件,报告写到 -o 指定路径;有问题时进程退出码为 1,可以接在 CI 或导出脚本后面阻止有风险的文件继续流转。

实际验证

项目包含 4 项标准库 unittest 测试:

  1. =、@ 和带制表符的公式前缀;
  2. -12.5、+100 的数值型正负号分类;
  3. 普通文本、空白和空单元格;
  4. 多行多列定位结果。

测试结果:

Ran 4 tests in 0.000s
OK

对三行合成 CSV 运行后,报告识别到 3 个问题:

{
  "rows": 4,
  "finding_count": 3,
  "safe": false
}

命中位置分别为第 3 行第 2 列、第 3 行第 3 列和第 4 行第 2 列,退出码为 1。

使用方式

python3 csv_formula_audit.py input.csv -o report.json
python3 -m unittest discover -s tests -v

生产落地建议

将检查器放在“生成 CSV”和“发布下载链接”之间,并把报告、输入文件哈希和构建编号一起归档。真正修复时可选择:

  • 对用户可见文本做平台约定范围内的前缀转义;
  • 对纯数值字段使用数值类型并在导出时格式化;
  • 在打开电子表格前增加数据来源提示和人工复核。

不要把“把内容用双引号包起来”当成安全修复:CSV 引号解决的是字段边界,不等于阻止电子表格解释单元格公式。

小结

公式注入检查不应该偷偷修改数据,而应先把风险变成可定位、可解释、可审计的记录。零依赖的 csv.reader 加上明确的前缀分类,已经足以让导出流程在交付前多一道可靠检查。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。