ActiveAdmin: Prevent command execution in CSV export file
Problem
A malicious user can change a database field so that when an administrator uses the Export functionality and opens the exported CSV in a spreadsheet editor such as Excel, code may be run on the administrator's computer. Alternatively, a malicious or compromised administrator can add or modify users with formulas in various fields to target other application administrators and users.
See: https://wiki.mozilla.org/images/6/6f/Phpmyadmin-report.pdf
Solution
When performing a CSV Export, for any cell that starts with an =, -, ", @, or +, add a space to the beginning and remove any tab characters (0x09) in the cell. Alternatively, prepend each cell field with a single quote, so that their content will be read as text by a spreadsheet editor.
See: https://wiki.mozilla.org/images/6/6f/Phpmyadmin-report.pdf
Environment:
- activeadmin-1.3.1
- rails-5.2.0
# config/initializers/activeadmin_csv_escape.rb # module ActiveAdmin class CSVBuilder def build_row(resource, columns, options) columns.map do |column| encode escape(call_method_or_proc_on(resource, column.data)), options end end # Escape cell content to prevent arbitrary command execution (in Excel) # # "Recommendation: # When performing a CSV Export, for any cell that starts with an =, # -, ", @, or +, add a space to the beginning and remove any tab # characters (0x09) in the cell. Alternatively, prepend each cell # field with a single quote, so that their content will be read as # text by a spreadsheet editor." # See: https://wiki.mozilla.org/images/6/6f/Phpmyadmin-report.pdf # def escape(string) # Check if cell starts with an =, -, ", @, + %w[ = - " @ + ].each do |char| if string.to_s.start_with? char # Prepend with space string.prepend " " # Replace tab (0x09) with space string.gsub!("\t", ' ') end end return string end end end