🐛 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
This commit is contained in:
Andrey Antukh 2026-08-05 17:35:59 +02:00 committed by GitHub
parent 49276886f3
commit 4f7bb94bb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 52 additions and 4 deletions

View File

@ -39,4 +39,10 @@
{:permits 3} {:permits 3}
:create-file-snapshot/by-profile :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}}

View File

@ -14,22 +14,25 @@
[app.db :as db] [app.db :as db]
[app.email :as eml] [app.email :as eml]
[app.rpc :as-alias rpc] [app.rpc :as-alias rpc]
[app.rpc.climit :as-alias climit]
[app.rpc.commands.profile :as profile] [app.rpc.commands.profile :as profile]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.util.services :as sv])) [app.util.services :as sv]))
(declare ^:private send-user-feedback!) (declare ^:private send-user-feedback!)
(def ^:private schema:send-user-feedback (def schema:send-user-feedback
[:map {:title "send-user-feedback"} [:map {:title "send-user-feedback"}
[:subject [:string {:max 500}]] [:subject [:string {:max 500}]]
[:content [:string {:max 2500}]] [:content [:string {:max 2500}]]
[:type {:optional true} :string] [:type {:optional true} :string]
[:error-href {:optional true} [:string {:max 2500}]] [:error-href {:optional true} [:string {:max 2500}]]
[:error-report {:optional true} :string]]) [:error-report {:optional true} [:string {:max 1048576}]]])
(sv/defmethod ::send-user-feedback (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} ::sm/params schema:send-user-feedback}
[{:keys [::db/pool]} {:keys [::rpc/profile-id] :as params}] [{:keys [::db/pool]} {:keys [::rpc/profile-id] :as params}]
(when-not (contains? cf/flags :user-feedback) (when-not (contains? cf/flags :user-feedback)

View File

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