summaryrefslogtreecommitdiffhomepage
path: root/lib/axlsx/workbook/worksheet/cell.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/axlsx/workbook/worksheet/cell.rb')
-rw-r--r--lib/axlsx/workbook/worksheet/cell.rb37
1 files changed, 21 insertions, 16 deletions
diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb
index 364de1e9..5e2661c3 100644
--- a/lib/axlsx/workbook/worksheet/cell.rb
+++ b/lib/axlsx/workbook/worksheet/cell.rb
@@ -28,10 +28,9 @@ module Axlsx
# @option options [String] color an 8 letter rgb specification
# @option options [Number] formula_value The value to cache for a formula cell.
# @option options [Symbol] scheme must be one of :none, major, :minor
- # @option options [Boolean] escape_formulas - Whether to treat a value starting with an equal
- # sign as formula (default) or as simple string.
- # Allowing user generated data to be interpreted as formulas can be dangerous
- # (see https://www.owasp.org/index.php/CSV_Injection for details).
+ # @option options [Boolean] escape_formulas Whether to treat values starting with an equals
+ # sign as formulas or as literal strings. Allowing user-generated data to be interpreted as
+ # formulas is a security risk. See https://www.owasp.org/index.php/CSV_Injection for details.
def initialize(row, value = nil, options = {})
@row = row
# Do not use instance vars if not needed to use less RAM
@@ -40,15 +39,13 @@ module Axlsx
type = options.delete(:type) || cell_type_from_value(value)
self.type = type unless type == :string
- escape_formulas = options[:escape_formulas]
- self.escape_formulas = escape_formulas unless escape_formulas.nil?
-
val = options.delete(:style)
self.style = val unless val.nil? || val == 0
val = options.delete(:formula_value)
self.formula_value = val unless val.nil?
parse_options(options)
+ self.escape_formulas = row.worksheet.escape_formulas if escape_formulas.nil?
self.value = value
value.cell = self if contains_rich_text?
@@ -73,6 +70,10 @@ module Axlsx
CELL_TYPES = [:date, :time, :float, :integer, :richtext,
:string, :boolean, :iso_8601, :text].freeze
+ # Leading characters that indicate a formula.
+ # See: https://owasp.org/www-community/attacks/CSV_Injection
+ FORMULA_PREFIXES = ['-', '=', '+', '@', '%', '|', "\r", "\t"].freeze
+
# The index of the cellXfs item to be applied to this cell.
# @return [Integer]
# @see Axlsx::Styles
@@ -132,16 +133,17 @@ module Axlsx
self.value = @value unless !defined?(@value) || @value.nil?
end
- # Whether to treat a value starting with an equal
- # sign as formula (default) or as simple string.
- # Allowing user generated data to be interpreted as formulas can be dangerous
- # (see https://www.owasp.org/index.php/CSV_Injection for details).
+ # Whether to treat values starting with an equals sign as formulas or as literal strings.
+ # Allowing user-generated data to be interpreted as formulas is a security risk.
+ # See https://www.owasp.org/index.php/CSV_Injection for details.
# @return [Boolean]
attr_reader :escape_formulas
- def escape_formulas=(v)
- Axlsx.validate_boolean(v)
- @escape_formulas = v
+ # Sets whether to treat values starting with an equals sign as formulas or as literal strings.
+ # @param [Boolean] value The value to set.
+ def escape_formulas=(value)
+ Axlsx.validate_boolean(value)
+ @escape_formulas = value
end
# The value of this cell.
@@ -170,7 +172,8 @@ module Axlsx
!is_text_run? && # No inline styles
[email protected]? && # Not nil
[email protected]? && # Not empty
- [email protected]_with?(?=) # Not a formula
+ !is_formula? && # Not a formula
+ !is_array_formula? # Not an array formula
end
# The inline font_name property for the cell
@@ -384,10 +387,12 @@ module Axlsx
def is_formula?
return false if escape_formulas
- type == :string && @value.to_s.start_with?(?=)
+ type == :string && @value.to_s.start_with?(*FORMULA_PREFIXES)
end
def is_array_formula?
+ return false if escape_formulas
+
type == :string && @value.to_s.start_with?('{=') && @value.to_s.end_with?('}')
end