From f9336e56940fb9ae00ac7fd967eaf0ef974463c9 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 30 Jan 2018 15:58:05 -0800 Subject: [PATCH] Mangle cells that look a little bit like formulas in CSV files Summary: Fixes T12800. See that task for discussion. When a cell in a CSV begins with "=", "+", "-", or "@", mangle the content to discourage Excel from executing it. This is clumsy, but we support other formats (e.g., JSON) which preserve the data faithfully and you should probably be using JSON if you're going to do anything programmatic with it. We could add two formats or a checkbox or a warning or something but cells with these symbols are fairly rare anyway. Some possible exceptions I can think of are "user monograms" (but we don't export those right now) and "negative numbers" (but also no direct export today). We can add exceptions for those as they arise. Test Plan: Exported a task named `=cmd|'/C evil.exe'!A0`, saw the title get mangled with "(!)" in front. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T12800 Differential Revision: https://secure.phabricator.com/D18974 --- .../export/format/PhabricatorCSVExportFormat.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/infrastructure/export/format/PhabricatorCSVExportFormat.php b/src/infrastructure/export/format/PhabricatorCSVExportFormat.php index 67f0a4963a..8f3879d5fb 100644 --- a/src/infrastructure/export/format/PhabricatorCSVExportFormat.php +++ b/src/infrastructure/export/format/PhabricatorCSVExportFormat.php @@ -42,6 +42,16 @@ final class PhabricatorCSVExportFormat private function addRow(array $values) { $row = array(); foreach ($values as $value) { + + // Excel is extremely interested in executing arbitrary code it finds in + // untrusted CSV files downloaded from the internet. When a cell looks + // like it might be too tempting for Excel to ignore, mangle the value + // to dissuade remote code execution. See T12800. + + if (preg_match('/^\s*[+=@-]/', $value)) { + $value = '(!) '.$value; + } + if (preg_match('/\s|,|\"/', $value)) { $value = str_replace('"', '""', $value); $value = '"'.$value.'"';