mirror of
https://github.com/penpot/penpot.git
synced 2026-08-06 04:48:39 +00:00
🐛 Normalize string inputs to prevent unfiltered echo
Add normalize-string helper in app.common.data that trims whitespace and returns empty string for nil input. Apply to profile, team, and project string fields (fullname, lang, theme, name) before storage. AI-assisted-by: qwen3.7-plus
This commit is contained in:
parent
43e05c38bf
commit
19e8115e43
@ -258,7 +258,8 @@
|
|||||||
(validate-register-attempt! cfg params)
|
(validate-register-attempt! cfg params)
|
||||||
|
|
||||||
(let [email (profile/clean-email email)
|
(let [email (profile/clean-email email)
|
||||||
profile (profile/get-profile-by-email pool email)]
|
profile (profile/get-profile-by-email pool email)
|
||||||
|
fullname (d/normalize-string fullname)]
|
||||||
|
|
||||||
;; SECURITY: refuse to issue a prepared-register token when an active
|
;; SECURITY: refuse to issue a prepared-register token when an active
|
||||||
;; profile already exists for this email.
|
;; profile already exists for this email.
|
||||||
@ -359,6 +360,9 @@
|
|||||||
is-active (:is-active params false)
|
is-active (:is-active params false)
|
||||||
theme (:theme params nil)
|
theme (:theme params nil)
|
||||||
email (str/lower email)
|
email (str/lower email)
|
||||||
|
fullname (d/normalize-string (:fullname params))
|
||||||
|
locale (d/normalize-string locale)
|
||||||
|
theme (d/normalize-string theme)
|
||||||
|
|
||||||
photo-id (some->> (or (:oidc/picture props)
|
photo-id (some->> (or (:oidc/picture props)
|
||||||
(:google/picture props)
|
(:google/picture props)
|
||||||
@ -367,7 +371,7 @@
|
|||||||
(import-profile-picture cfg))
|
(import-profile-picture cfg))
|
||||||
|
|
||||||
params {:id id
|
params {:id id
|
||||||
:fullname (:fullname params)
|
:fullname fullname
|
||||||
:email email
|
:email email
|
||||||
:auth-backend backend
|
:auth-backend backend
|
||||||
:lang locale
|
:lang locale
|
||||||
|
|||||||
@ -163,6 +163,9 @@
|
|||||||
;; it or not for explicit locking and avoid concurrent updates of
|
;; it or not for explicit locking and avoid concurrent updates of
|
||||||
;; the same row/object.
|
;; the same row/object.
|
||||||
(let [profile (get-profile conn profile-id ::db/for-update true)
|
(let [profile (get-profile conn profile-id ::db/for-update true)
|
||||||
|
fullname (d/normalize-string fullname)
|
||||||
|
lang (d/normalize-string lang)
|
||||||
|
theme (d/normalize-string theme)
|
||||||
;; Update the profile map with direct params
|
;; Update the profile map with direct params
|
||||||
profile (-> profile
|
profile (-> profile
|
||||||
(assoc :fullname fullname)
|
(assoc :fullname fullname)
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
(ns app.rpc.commands.projects
|
(ns app.rpc.commands.projects
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
@ -259,7 +260,8 @@
|
|||||||
::db/transaction true}
|
::db/transaction true}
|
||||||
[{:keys [::db/conn]} {:keys [::rpc/profile-id id name] :as params}]
|
[{:keys [::db/conn]} {:keys [::rpc/profile-id id name] :as params}]
|
||||||
(check-edition-permissions! conn profile-id id)
|
(check-edition-permissions! conn profile-id id)
|
||||||
(let [project (db/get-by-id conn :project id ::sql/for-update true)]
|
(let [project (db/get-by-id conn :project id ::sql/for-update true)
|
||||||
|
name (d/normalize-string name)]
|
||||||
(db/update! conn :project
|
(db/update! conn :project
|
||||||
{:name name}
|
{:name name}
|
||||||
{:id id})
|
{:id id})
|
||||||
|
|||||||
@ -652,6 +652,7 @@
|
|||||||
(let [id (or id (uuid/next))
|
(let [id (or id (uuid/next))
|
||||||
is-default (if (boolean? is-default) is-default false)
|
is-default (if (boolean? is-default) is-default false)
|
||||||
features (db/create-array conn "text" features)
|
features (db/create-array conn "text" features)
|
||||||
|
name (d/normalize-string name)
|
||||||
team (db/insert! conn :team
|
team (db/insert! conn :team
|
||||||
{:id id
|
{:id id
|
||||||
:name name
|
:name name
|
||||||
@ -688,6 +689,7 @@
|
|||||||
[conn {:keys [id team-id name is-default created-at modified-at]}]
|
[conn {:keys [id team-id name is-default created-at modified-at]}]
|
||||||
(let [id (or id (uuid/next))
|
(let [id (or id (uuid/next))
|
||||||
is-default (if (boolean? is-default) is-default false)
|
is-default (if (boolean? is-default) is-default false)
|
||||||
|
name (d/normalize-string name)
|
||||||
params {:id id
|
params {:id id
|
||||||
:name name
|
:name name
|
||||||
:team-id team-id
|
:team-id team-id
|
||||||
@ -718,9 +720,10 @@
|
|||||||
::db/transaction true}
|
::db/transaction true}
|
||||||
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id id name]}]
|
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id id name]}]
|
||||||
(check-edition-permissions! conn profile-id id)
|
(check-edition-permissions! conn profile-id id)
|
||||||
(db/update! conn :team
|
(let [name (d/normalize-string name)]
|
||||||
{:name name}
|
(db/update! conn :team
|
||||||
{:id id})
|
{:name name}
|
||||||
|
{:id id}))
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1173,6 +1173,15 @@
|
|||||||
[key coll]
|
[key coll]
|
||||||
(sort-by key natural-compare coll))
|
(sort-by key natural-compare coll))
|
||||||
|
|
||||||
|
(defn normalize-string
|
||||||
|
"Normalizes a string by trimming leading/trailing whitespace.
|
||||||
|
Returns empty string for nil input. Non-string input is returned unchanged."
|
||||||
|
[s]
|
||||||
|
(cond
|
||||||
|
(nil? s) ""
|
||||||
|
(string? s) (str/trim s)
|
||||||
|
:else s))
|
||||||
|
|
||||||
(defn sanitize-string [s]
|
(defn sanitize-string [s]
|
||||||
(if s
|
(if s
|
||||||
(-> s
|
(-> s
|
||||||
|
|||||||
@ -36,6 +36,24 @@
|
|||||||
(t/is (= "" (d/get-initials nil)))
|
(t/is (= "" (d/get-initials nil)))
|
||||||
(t/is (= "" (d/get-initials "!!! ???"))))
|
(t/is (= "" (d/get-initials "!!! ???"))))
|
||||||
|
|
||||||
|
(t/deftest normalize-string-test
|
||||||
|
;; nil input returns empty string
|
||||||
|
(t/is (= "" (d/normalize-string nil)))
|
||||||
|
;; empty string returns empty string
|
||||||
|
(t/is (= "" (d/normalize-string "")))
|
||||||
|
;; leading whitespace is trimmed
|
||||||
|
(t/is (= "hello" (d/normalize-string " hello")))
|
||||||
|
;; trailing whitespace is trimmed
|
||||||
|
(t/is (= "hello" (d/normalize-string "hello ")))
|
||||||
|
;; both leading and trailing whitespace are trimmed
|
||||||
|
(t/is (= "hello" (d/normalize-string " hello ")))
|
||||||
|
;; internal whitespace is preserved
|
||||||
|
(t/is (= "hello world" (d/normalize-string " hello world ")))
|
||||||
|
;; non-string input is returned unchanged
|
||||||
|
(t/is (= 42 (d/normalize-string 42)))
|
||||||
|
(t/is (= :keyword (d/normalize-string :keyword)))
|
||||||
|
(t/is (= true (d/normalize-string true))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Ordered Data Structures
|
;; Ordered Data Structures
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user