discourse/spec/models/theme_setting_spec.rb
Alan Guo Xiang Tan 3e331b1725
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.
2024-02-21 08:09:37 +08:00

55 lines
1.8 KiB
Ruby

# frozen_string_literal: true
RSpec.describe ThemeSetting do
fab!(:theme)
context "for validations" do
it "should be invalid when setting data_type to objects and `experimental_objects_type_for_theme_settings` is disabled" do
SiteSetting.experimental_objects_type_for_theme_settings = false
theme_setting =
ThemeSetting.new(name: "test", data_type: ThemeSetting.types[:objects], theme:)
expect(theme_setting.valid?).to eq(false)
expect(theme_setting.errors[:data_type]).to contain_exactly("is not included in the list")
end
it "should be valid when setting data_type to objects and `experimental_objects_type_for_theme_settings` is enabled" do
SiteSetting.experimental_objects_type_for_theme_settings = true
theme_setting =
ThemeSetting.new(name: "test", data_type: ThemeSetting.types[:objects], theme:)
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