Skip to content

CSV export writes command and parameter values unescaped, allowing spreadsheet formula injection when the exported file is opened #915

Description

@carfeii

Summary

hyperfine --export-csv writes each benchmarked command's name and every
--parameter-list/--parameter-scan value into the CSV file with no
protection against spreadsheet formula interpretation
(CsvExporter::serialize, src/export/csv.rs). Excel, LibreOffice Calc,
and Google Sheets all treat a cell beginning with =, +, -, or @ as
a formula to evaluate on open, independent of the file's .csv
extension. Since both the command string and any parameter value are
attacker-influenceable in workflows where hyperfine parameterizes a
benchmark over externally-submitted names (for example, comparing a list
of community-submitted package or command variants in CI), a benchmark
run driven that way and exported to CSV for someone else to review
produces a file that executes an attacker-chosen formula the moment that
person opens it. This is CWE-1236.

Validated against v1.20.0.

POC

(available upon request)

Impact

Confirmed: a --parameter-list payload '=1+1' run exported to CSV
contains the literal, unescaped text =1+1. Opening the file in
LibreOffice Calc (verified via headless conversion) evaluates the cell
and shows 2, confirming the exported value is interpreted as a live
formula rather than displayed as text. A stronger payload is a documented
extension of the same mechanism: a HYPERLINK/WEBSERVICE-style formula
can exfiltrate other cell contents to an attacker-controlled URL, and
legacy DDE formula syntax has historically enabled command execution in
older Excel versions. Neither was tested here; confirming formula
evaluation was sufficient to establish the defect.

Suggested Fix

Before writing a value into a CSV cell, check whether it begins with =,
+, -, @, a tab, or a carriage return, and if so, prefix it with a
single quote so spreadsheet applications display it as literal text
instead of evaluating it. This is the standard mitigation for CWE-1236.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions