From 4f7bb94bb1f00037dd6d2c0b2aa2c2a7e87c0ddb Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 5 Aug 2026 17:35:59 +0200 Subject: [PATCH] :bug: Add size limit and rate limiting to send-user-feedback (#10979) (#10990) Prevent email bombing attacks on the send-user-feedback endpoint by limiting the error-report field to 1MiB and adding climit rate limits: by-profile (1 permit, queue 3) and global (4 permits), configured in climit.edn. Make the schema public so it can be exercised by tests, and add schema validation tests covering the new size limit. AI-assisted-by: qwen3.7-plus --- backend/resources/climit.edn | 8 +++- backend/src/app/rpc/commands/feedback.clj | 9 +++-- .../test/backend_tests/rpc_feedback_test.clj | 39 +++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 backend/test/backend_tests/rpc_feedback_test.clj diff --git a/backend/resources/climit.edn b/backend/resources/climit.edn index 7d8234499b..66ac82b174 100644 --- a/backend/resources/climit.edn +++ b/backend/resources/climit.edn @@ -39,4 +39,10 @@ {:permits 3} :create-file-snapshot/by-profile - {:permits 1 :queue 2 :timeout 60000}} + {:permits 1 :queue 2 :timeout 60000} + + :send-user-feedback/global + {:permits 4} + + :send-user-feedback/by-profile + {:permits 1 :queue 3}} diff --git a/backend/src/app/rpc/commands/feedback.clj b/backend/src/app/rpc/commands/feedback.clj index 565f41d30e..b70341fc33 100644 --- a/backend/src/app/rpc/commands/feedback.clj +++ b/backend/src/app/rpc/commands/feedback.clj @@ -14,22 +14,25 @@ [app.db :as db] [app.email :as eml] [app.rpc :as-alias rpc] + [app.rpc.climit :as-alias climit] [app.rpc.commands.profile :as profile] [app.rpc.doc :as-alias doc] [app.util.services :as sv])) (declare ^:private send-user-feedback!) -(def ^:private schema:send-user-feedback +(def schema:send-user-feedback [:map {:title "send-user-feedback"} [:subject [:string {:max 500}]] [:content [:string {:max 2500}]] [:type {:optional true} :string] [:error-href {:optional true} [:string {:max 2500}]] - [:error-report {:optional true} :string]]) + [:error-report {:optional true} [:string {:max 1048576}]]]) (sv/defmethod ::send-user-feedback - {::doc/added "1.18" + {::climit/id [[:send-user-feedback/by-profile ::rpc/profile-id] + [:send-user-feedback/global]] + ::doc/added "1.18" ::sm/params schema:send-user-feedback} [{:keys [::db/pool]} {:keys [::rpc/profile-id] :as params}] (when-not (contains? cf/flags :user-feedback) diff --git a/backend/test/backend_tests/rpc_feedback_test.clj b/backend/test/backend_tests/rpc_feedback_test.clj new file mode 100644 index 0000000000..13231db61b --- /dev/null +++ b/backend/test/backend_tests/rpc_feedback_test.clj @@ -0,0 +1,39 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC Sucursal en EspaƱa SL + +(ns backend-tests.rpc-feedback-test + (:require + [app.common.schema :as sm] + [app.rpc.commands.feedback :as feedback] + [clojure.test :as t])) + +(t/deftest send-user-feedback-schema-validation + (let [schema feedback/schema:send-user-feedback] + + (t/testing "accepts valid feedback with all fields" + (let [params {:subject "Test subject" + :content "Test content" + :type "bug" + :error-href "https://example.com/error" + :error-report "Error details here"}] + (t/is (sm/valid? schema params)))) + + (t/testing "accepts feedback without optional fields" + (let [params {:subject "Test subject" + :content "Test content"}] + (t/is (sm/valid? schema params)))) + + (t/testing "accepts error-report up to 1MiB" + (let [params {:subject "Test subject" + :content "Test content" + :error-report (apply str (repeat 1048576 "x"))}] + (t/is (sm/valid? schema params)))) + + (t/testing "rejects error-report exceeding 1MiB" + (let [params {:subject "Test subject" + :content "Test content" + :error-report (apply str (repeat 1048577 "x"))}] + (t/is (not (sm/valid? schema params)))))))