mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 13:29:07 +00:00
🐛 Validate font-id team ownership in create-font-variant
Prevent cross-team font injection by checking that when a font-id already has variants, they belong to the same team. This closes a BOLA gap where a user with team edit permissions could create a font variant referencing a font-id from another team. AI-assisted-by: mimo-v2.5-pro
This commit is contained in:
parent
319a2185c9
commit
20a2c5fcbf
@ -95,6 +95,18 @@
|
|||||||
|
|
||||||
(declare create-font-variant)
|
(declare create-font-variant)
|
||||||
|
|
||||||
|
(defn- check-font-team-ownership!
|
||||||
|
"When font-id already has variants belonging to a different team,
|
||||||
|
raises :not-found to prevent cross-team font injection."
|
||||||
|
[conn team-id font-id]
|
||||||
|
(let [row (db/get* conn :team-font-variant
|
||||||
|
{:font-id font-id}
|
||||||
|
{::db/columns [:team-id]})]
|
||||||
|
(when (and row (not= (:team-id row) team-id))
|
||||||
|
(ex/raise :type :not-found
|
||||||
|
:code :object-not-found
|
||||||
|
:hint "font does not belong to this team"))))
|
||||||
|
|
||||||
(def ^:private schema:create-font-variant
|
(def ^:private schema:create-font-variant
|
||||||
[:and
|
[:and
|
||||||
[:map {:title "create-font-variant"}
|
[:map {:title "create-font-variant"}
|
||||||
@ -168,8 +180,9 @@
|
|||||||
[:process-font/global]]
|
[:process-font/global]]
|
||||||
::webhooks/event? true
|
::webhooks/event? true
|
||||||
::sm/params schema:create-font-variant}
|
::sm/params schema:create-font-variant}
|
||||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id uploads] :as params}]
|
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id font-id uploads] :as params}]
|
||||||
(teams/check-edition-permissions! pool profile-id team-id)
|
(teams/check-edition-permissions! pool profile-id team-id)
|
||||||
|
(check-font-team-ownership! pool team-id font-id)
|
||||||
(quotes/check! cfg {::quotes/id ::quotes/font-variants-per-team
|
(quotes/check! cfg {::quotes/id ::quotes/font-variants-per-team
|
||||||
::quotes/profile-id profile-id
|
::quotes/profile-id profile-id
|
||||||
::quotes/team-id team-id})
|
::quotes/team-id team-id})
|
||||||
|
|||||||
@ -922,3 +922,43 @@
|
|||||||
:name "Valid Font Name"}
|
:name "Valid Font Name"}
|
||||||
out (th/command! params)]
|
out (th/command! params)]
|
||||||
(t/is (th/success? out))))))
|
(t/is (th/success? out))))))
|
||||||
|
|
||||||
|
(t/deftest create-font-variant-rejects-foreign-font-id
|
||||||
|
;; N2-07: A user with edit permissions on their own team must not be
|
||||||
|
;; able to create a font variant using a font-id that already belongs
|
||||||
|
;; to another team (BOLA / CWE-639).
|
||||||
|
(with-mocks [mock {:target 'app.rpc.quotes/check! :return nil}]
|
||||||
|
(let [prof1 (th/create-profile* 1 {:is-active true})
|
||||||
|
prof2 (th/create-profile* 2 {:is-active true})
|
||||||
|
team1 (:default-team-id prof1)
|
||||||
|
team2 (:default-team-id prof2)
|
||||||
|
font-id (uuid/custom 10 999)
|
||||||
|
data (-> (io/resource "backend_tests/test_files/font-1.ttf")
|
||||||
|
(io/read*))]
|
||||||
|
|
||||||
|
;; prof1 creates a font variant in team1 with font-id
|
||||||
|
(let [params {::th/type :create-font-variant
|
||||||
|
::rpc/profile-id (:id prof1)
|
||||||
|
:team-id team1
|
||||||
|
:font-id font-id
|
||||||
|
:font-family "SharedFont"
|
||||||
|
:font-weight 400
|
||||||
|
:font-style "normal"
|
||||||
|
:data {"font/ttf" data}}
|
||||||
|
out (th/command! params)]
|
||||||
|
(t/is (nil? (:error out))))
|
||||||
|
|
||||||
|
;; prof2 tries to create a variant using the same font-id but
|
||||||
|
;; in team2 — must be rejected because font-id belongs to team1
|
||||||
|
(let [params {::th/type :create-font-variant
|
||||||
|
::rpc/profile-id (:id prof2)
|
||||||
|
:team-id team2
|
||||||
|
:font-id font-id
|
||||||
|
:font-family "SharedFont"
|
||||||
|
:font-weight 700
|
||||||
|
:font-style "normal"
|
||||||
|
:data {"font/ttf" data}}
|
||||||
|
out (th/command! params)]
|
||||||
|
(t/is (some? (:error out)))
|
||||||
|
(t/is (= :not-found (-> out :error ex-data :type)))
|
||||||
|
(t/is (= :object-not-found (-> out :error ex-data :code)))))))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user