mirror of
https://github.com/discourse/discourse.git
synced 2025-01-18 14:03:18 +08:00
DEV: Set a bytesize limit for ThemeSetting#json_value
(#25761)
Why this change? Firstly, note that this is not a security commit because this feature is still in development and should not be used anywhere. The reason we want to set a limit here is to greatly reduce the possibility of a DoS attack in the future via `ThemeSetting` where someone would set an arbituary large json string in `ThemeSetting#json_value` and causing the server to run out of resources trying to serialize/deserialize the value. What does this change do? Adds an ActiveRecord validation to ensure that the bytesize of the json string being stored is smaller than or equal to 0.5mb. We believe 0.5mb is a decent limit for now but we can review the limit in the future if we believe it is too small.
This commit is contained in:
parent
6ca2396b12
commit
3e331b1725
|
@ -8,9 +8,12 @@ class ThemeSetting < ActiveRecord::Base
|
|||
TYPES_ENUM =
|
||||
Enum.new(integer: 0, float: 1, string: 2, bool: 3, list: 4, enum: 5, upload: 6, objects: 7)
|
||||
|
||||
MAXIMUM_JSON_VALUE_SIZE_BYTES = 0.5 * 1024 * 1024 # 0.5 MB
|
||||
|
||||
validates_presence_of :name, :theme
|
||||
before_validation :objects_type_enabled
|
||||
validates :data_type, inclusion: { in: TYPES_ENUM.values }
|
||||
validate :json_value_size, if: -> { self.data_type == TYPES_ENUM[:objects] }
|
||||
validates :name, length: { maximum: 255 }
|
||||
|
||||
after_save :clear_settings_cache
|
||||
|
@ -52,6 +55,18 @@ class ThemeSetting < ActiveRecord::Base
|
|||
self.data_type = nil
|
||||
end
|
||||
end
|
||||
|
||||
def json_value_size
|
||||
if json_value.to_json.size > MAXIMUM_JSON_VALUE_SIZE_BYTES
|
||||
errors.add(
|
||||
:json_value,
|
||||
I18n.t(
|
||||
"theme_settings.errors.json_value.too_large",
|
||||
max_size_megabytes: MAXIMUM_JSON_VALUE_SIZE_BYTES / 1024 / 1024,
|
||||
),
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
@ -74,6 +74,10 @@ en:
|
|||
enabled_filter: "Enabled"
|
||||
disabled_filter: "Disabled"
|
||||
updates_available_filter: "Updates Available"
|
||||
theme_settings:
|
||||
errors:
|
||||
json_value:
|
||||
too_large: "has exceeded the maximum size of %{max_size} bytes."
|
||||
themes:
|
||||
bad_color_scheme: "Can not update theme, invalid color palette"
|
||||
other_error: "Something went wrong updating theme"
|
||||
|
|
|
@ -22,5 +22,33 @@ RSpec.describe ThemeSetting do
|
|||
|
||||
expect(theme_setting.valid?).to eq(true)
|
||||
end
|
||||
|
||||
it "should be invalid when json_value size is greater than the maximum allowed size" do
|
||||
SiteSetting.experimental_objects_type_for_theme_settings = true
|
||||
|
||||
json_value = { "key" => "value" }
|
||||
bytesize = json_value.to_json.bytesize
|
||||
|
||||
expect(bytesize).to eq(15)
|
||||
|
||||
stub_const(ThemeSetting, "MAXIMUM_JSON_VALUE_SIZE_BYTES", bytesize - 1) do
|
||||
theme_setting =
|
||||
ThemeSetting.new(
|
||||
name: "test",
|
||||
data_type: ThemeSetting.types[:objects],
|
||||
theme:,
|
||||
json_value:,
|
||||
)
|
||||
|
||||
expect(theme_setting.valid?).to eq(false)
|
||||
|
||||
expect(theme_setting.errors[:json_value]).to contain_exactly(
|
||||
I18n.t(
|
||||
"theme_settings.errors.json_value.too_large",
|
||||
max_size_megabytes: (bytesize - 1) / 1024 / 1024,
|
||||
),
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user