From bae200edd754ebd04a32d30ba2c66a81d5612ed0 Mon Sep 17 00:00:00 2001 From: snipe Date: Fri, 30 Sep 2022 09:29:17 -0700 Subject: [PATCH 1/4] Use EscapeFormula() in CSV export Signed-off-by: snipe --- app/Http/Controllers/ReportsController.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index c7e5bf74a..f3d692474 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -22,7 +22,7 @@ use Illuminate\Support\Facades\View; use Input; use League\Csv\Reader; use Symfony\Component\HttpFoundation\StreamedResponse; - +use League\Csv\EscapeFormula; /** * This controller handles all actions related to Reports for * the Snipe-IT Asset Management application. @@ -666,6 +666,9 @@ class ReportsController extends Controller $executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']; \Log::debug('Walking results: '.$executionTime); $count = 0; + + $formatter = new EscapeFormula("`"); + foreach ($assets as $asset) { $count++; $row = []; @@ -855,7 +858,7 @@ class ReportsController extends Controller $row[] = $asset->$column_name; } } - fputcsv($handle, $row); + fputcsv($handle, $formatter->escapeRecord($row)); $executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']; \Log::debug('-- Record '.$count.' Asset ID:'.$asset->id.' in '.$executionTime); } From 5a7e35c0e8b399fb18db5bc3435d1628d95996e3 Mon Sep 17 00:00:00 2001 From: snipe Date: Fri, 30 Sep 2022 09:48:43 -0700 Subject: [PATCH 2/4] Made a conditional escape according to .env Signed-off-by: snipe --- .env.example | 1 + app/Http/Controllers/ReportsController.php | 13 ++++++++++++- config/app.php | 18 +++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 72aafd007..e77fb5f11 100644 --- a/.env.example +++ b/.env.example @@ -173,3 +173,4 @@ IMPORT_MEMORY_LIMIT=500M REPORT_TIME_LIMIT=12000 REQUIRE_SAML=false API_THROTTLE_PER_MINUTE=120 +CSV_ESCAPE_FORMULAS=true diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index f3d692474..78972a46e 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -411,6 +411,7 @@ class ReportsController extends Controller $customfields = CustomField::get(); $response = new StreamedResponse(function () use ($customfields, $request) { \Log::debug('Starting streamed response'); + \Log::debug('CSV escaping is set to: '.config('app.escape_formulas')); // Open output stream $handle = fopen('php://output', 'w'); @@ -858,7 +859,17 @@ class ReportsController extends Controller $row[] = $asset->$column_name; } } - fputcsv($handle, $formatter->escapeRecord($row)); + + + // CSV_ESCAPE_FORMULAS is set to false in the .env + if (config('app.escape_formulas') === false) { + fputcsv($handle, $row); + + // CSV_ESCAPE_FORMULAS is set to true or is not set in the .env + } else { + fputcsv($handle, $formatter->escapeRecord($row)); + } + $executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']; \Log::debug('-- Record '.$count.' Asset ID:'.$asset->id.' in '.$executionTime); } diff --git a/config/app.php b/config/app.php index c3627ddea..8833ea2ae 100755 --- a/config/app.php +++ b/config/app.php @@ -394,7 +394,7 @@ return [ 'allow_purge' => env('ALLOW_DATA_PURGE', false), - /* + /* |-------------------------------------------------------------------------- | Allow Backup Deletion |-------------------------------------------------------------------------- @@ -405,4 +405,20 @@ return [ 'allow_backup_delete' => env('ALLOW_BACKUP_DELETE', false), + + /* + |-------------------------------------------------------------------------- + | Escape Excel formulas in CSV exports + |-------------------------------------------------------------------------- + | + | This determins whether or not we should escape Excel formulas in CSV exports. + | This can be UNSAFE in untrusted environments, and therefore defaults to true + | so that Excel forumals WILL be escaped in CSV exports, however if your workflow + | is designed around using formulas in your fields, you + | you can set CSV_ESCAPE_FORMULAS to 'false' in your .env. + | + */ + + 'escape_formulas' => env('CSV_ESCAPE_FORMULAS', true), + ]; From aa52bc6c6a77362539bb6e340cc16f49b5e73583 Mon Sep 17 00:00:00 2001 From: snipe Date: Fri, 30 Sep 2022 11:47:20 -0700 Subject: [PATCH 3/4] Added Vautia Signed-off-by: snipe --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 43ffa39e8..0498f5b5a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2729,6 +2729,15 @@ "contributions": [ "code" ] + }, + { + "login": "Vautia", + "name": "Vautia", + "avatar_url": "https://avatars.githubusercontent.com/u/111710123?v=4", + "profile": "https://github.com/Vautia", + "contributions": [ + "security" + ] } ] } From b07c4caa3713cbd9bb9811a0735e5624cd566720 Mon Sep 17 00:00:00 2001 From: snipe Date: Fri, 30 Sep 2022 11:47:27 -0700 Subject: [PATCH 4/4] Extra whitespace Signed-off-by: snipe --- app/Http/Controllers/ReportsController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php index 78972a46e..324dc2638 100644 --- a/app/Http/Controllers/ReportsController.php +++ b/app/Http/Controllers/ReportsController.php @@ -23,6 +23,8 @@ use Input; use League\Csv\Reader; use Symfony\Component\HttpFoundation\StreamedResponse; use League\Csv\EscapeFormula; + + /** * This controller handles all actions related to Reports for * the Snipe-IT Asset Management application.