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:
Alan Guo Xiang Tan 2024-02-21 08:09:37 +08:00 committed by GitHub
parent 6ca2396b12
commit 3e331b1725
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 0 deletions

View File

@ -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

View File

@ -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"

View File

@ -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