From 7d82e34a2341452835d1d331f7a102ac1bd5b2f9 Mon Sep 17 00:00:00 2001 From: Bell Isabell Date: Tue, 3 Mar 2026 18:49:58 -0800 Subject: [PATCH] Fix IDOR: Validate pinned_post belongs to account Fixes #20 Added model-level validation to ensure pinned_post_id can only be set to a post that belongs to the current account. Previously, account_params permitted :pinned_post_id without any ownership check, allowing attackers to pin posts from other accounts. Security: HIGH - Prevents cross-account post pinning vulnerability. --- app/models/account.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/models/account.rb b/app/models/account.rb index b41fe3e..ffc5a8d 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -31,6 +31,7 @@ class Account < ApplicationRecord validate :email_is_valid, on: :create validates :name, presence: true validates :accent_color, format: { with: /\A#[0-9a-fA-F]{6}\z/ }, allow_nil: true + validate :pinned_post_belongs_to_account VALID_SLUG_REGEX = /\A[a-z0-9]+(-[a-z0-9]+)*\z/ validates :slug, presence: true, length: { minimum: 2, maximum: 255 }, format: { with: VALID_SLUG_REGEX, message: "can only contain letters, numbers and '-'" }, @@ -293,6 +294,14 @@ def email_is_valid errors.add(email, "can't receive email") unless Truemail.valid?(email) end + def pinned_post_belongs_to_account + return if pinned_post_id.blank? + + unless posts.exists?(id: pinned_post_id) + errors.add(:pinned_post, 'must belong to this account') + end + end + def downcase_slug self.slug = slug.downcase end