SECURITY: Limit invites params length

This commit is contained in:
Penar Musaraj 2024-02-19 16:34:40 -05:00 committed by Nat
parent c41755bd69
commit bcc556b956
No known key found for this signature in database
GPG Key ID: 4938B35D927EC773
3 changed files with 56 additions and 2 deletions

View File

@ -32,8 +32,9 @@ class Invite < ActiveRecord::Base
has_many :topics, through: :topic_invites, source: :topic has_many :topics, through: :topic_invites, source: :topic
validates_presence_of :invited_by_id validates_presence_of :invited_by_id
validates :email, email: true, allow_blank: true validates :email, email: true, allow_blank: true, length: { maximum: 500 }
validates :custom_message, length: { maximum: 1000 } validates :custom_message, length: { maximum: 1000 }
validates :domain, length: { maximum: 500 }
validate :ensure_max_redemptions_allowed validate :ensure_max_redemptions_allowed
validate :valid_redemption_count validate :valid_redemption_count
validate :valid_domain, if: :will_save_change_to_domain? validate :valid_domain, if: :will_save_change_to_domain?
@ -350,7 +351,7 @@ class Invite < ActiveRecord::Base
self.domain.downcase! self.domain.downcase!
if self.domain !~ Invite::DOMAIN_REGEX if self.domain !~ Invite::DOMAIN_REGEX
self.errors.add(:base, I18n.t("invite.domain_not_allowed")) self.errors.add(:base, I18n.t("invite.domain_not_allowed_admin"))
end end
end end

View File

@ -303,6 +303,7 @@ en:
requires_groups: "Invite was not saved because the specified topic is inaccessible. Add one of the following groups: %{groups}." requires_groups: "Invite was not saved because the specified topic is inaccessible. Add one of the following groups: %{groups}."
max_invite_emails_limit_exceeded: "Request failed because number of emails exceeded the maximum (%{max})." max_invite_emails_limit_exceeded: "Request failed because number of emails exceeded the maximum (%{max})."
domain_not_allowed: "Your email cannot be used to redeem this invite." domain_not_allowed: "Your email cannot be used to redeem this invite."
domain_not_allowed_admin: "This domain cannot be used for invites."
max_redemptions_allowed_one: "for email invites should be 1." max_redemptions_allowed_one: "for email invites should be 1."
redemption_count_less_than_max: "should be less than %{max_redemptions_allowed}." redemption_count_less_than_max: "should be less than %{max_redemptions_allowed}."
email_xor_domain: "Email and domain fields are not allowed at the same time" email_xor_domain: "Email and domain fields are not allowed at the same time"

View File

@ -433,6 +433,18 @@ RSpec.describe InvitesController do
end end
end end
context "when email address is too long" do
let(:email) { "a" * 495 + "@example.com" }
it "fails" do
create_invite
expect(response).to have_http_status :unprocessable_entity
expect(response.parsed_body["errors"]).to be_present
error_message = response.parsed_body["errors"].first
expect(error_message).to eq("Email is too long (maximum is 500 characters)")
end
end
context "when providing an email belonging to an existing user" do context "when providing an email belonging to an existing user" do
let(:email) { user.email } let(:email) { user.email }
@ -460,6 +472,46 @@ RSpec.describe InvitesController do
end end
end end
context "with domain invite" do
it "works" do
sign_in(admin)
post "/invites.json", params: { domain: "example.com" }
expect(response).to have_http_status :ok
end
it "fails when domain is invalid" do
sign_in(admin)
post "/invites.json", params: { domain: "example" }
expect(response).to have_http_status :unprocessable_entity
error_message = response.parsed_body["errors"].first
expect(error_message).to eq(I18n.t("invite.domain_not_allowed_admin"))
end
it "fails when domain is too long" do
sign_in(admin)
post "/invites.json", params: { domain: "a" * 500 + ".ca" }
expect(response).to have_http_status :unprocessable_entity
error_message = response.parsed_body["errors"].first
expect(error_message).to eq("Domain is too long (maximum is 500 characters)")
end
it "fails when custom message is too long" do
sign_in(admin)
post "/invites.json", params: { custom_message: "b" * 1001, domain: "example.com" }
expect(response).to have_http_status :unprocessable_entity
error_message = response.parsed_body["errors"].first
expect(error_message).to eq("Custom message is too long (maximum is 1000 characters)")
end
end
context "with link invite" do context "with link invite" do
it "works" do it "works" do
sign_in(admin) sign_in(admin)