Skip to content
Permalink
Browse files Browse the repository at this point in the history
Escape user entered HTML in several different locations throughout th…
…e UI, to help mitigate against XSS attacks.
  • Loading branch information
mschaef committed Oct 28, 2022
1 parent 862e84b commit fdc825a
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 48 deletions.
47 changes: 26 additions & 21 deletions src/toto/todo/todo_list.clj
Expand Up @@ -28,8 +28,8 @@
toto.view.query
toto.view.page)
(:require [clojure.tools.logging :as log]
[hiccup.form :as form]
[hiccup.util :as util]
[hiccup.form :as hiccup-form]
[hiccup.util :as hiccup-util]
[toto.data.data :as data]
[toto.view.auth :as auth]
[toto.view.request-date :as request-date]
Expand All @@ -42,8 +42,8 @@
(defn- format-date [ date ]
(.format pill-date-format date))

(defn ensure-string-breakpoints [ s n ]
(clojure.string/join html-breakpoint (partition-string s n)))
(defn- ensure-string-breakpoints [ s n ]
(clojure.string/join html-breakpoint (map hiccup-util/escape-html (partition-string s n))))

(defn- ensure-string-breaks [ string at ]
(clojure.string/replace string at (str at html-breakpoint)))
Expand All @@ -54,7 +54,7 @@
":"
(if-let [authority (.getAuthority url)]
(str "//" authority)))]
(-> (util/escape-html
(-> (hiccup-util/escape-html
(str base
(string-leftmost (.getPath url)
(max 0 (- (- target-length 3) (.length base)))
Expand Down Expand Up @@ -99,22 +99,23 @@

(defn- render-new-item-form [ list-id editing-item? ]
(let [ sublists (data/get-view-sublists (auth/current-user-id) list-id)]
(form/form-to
(hiccup-form/form-to
{:class "new-item-form"}
[:post (shref "/list/" list-id)]
(if (= (count sublists) 0)
(form/hidden-field "item-list-id" list-id)
(hiccup-form/hidden-field "item-list-id" list-id)
[:select {:id "item-list-id" :name "item-list-id"}
(form/select-options (map (fn [ sublist ]
[ (:desc sublist) (:sublist_id sublist)])
(hiccup-form/select-options (map (fn [ sublist ]
[(hiccup-util/escape-html (:desc sublist))
(:sublist_id sublist)])
sublists))])
(form/text-field (cond-> {:maxlength "1024"
(hiccup-form/text-field (cond-> {:maxlength "1024"
:placeholder "New Item Description"
:autocomplete "off"
:onkeydown "window._toto.onNewItemInputKeydown(event)"}
(not editing-item?) (assoc "autofocus" "on"))
"item-description")
(form/hidden-field "item-priority" "0")
(hiccup-form/hidden-field "item-priority" "0")
[:button.high-priority-submit {:type "button"
:onclick "window._toto.submitHighPriority()"}
img-star-yellow])))
Expand Down Expand Up @@ -200,14 +201,15 @@
", snoozed: " (format-date snoozed-until)))])
(when (not (= created-by-id (auth/current-user-id)))
[:span.pill { :title created-by-email }
created-by-name])]))]
(hiccup-util/escape-html
created-by-name)])]))]
[:div.item-control.priority.right
(render-item-priority-control item-id priority writable?)]
(item-drag-handle "right" item-info)]))

(defn- render-query-select [ id current-value ]
[:select { :id id :name id :onchange "this.form.submit()"}
(form/select-options [[ "-" "-"]
(hiccup-form/select-options [[ "-" "-"]
["1d" "1"]
["7d" "7"]
["30d" "30"]
Expand All @@ -218,7 +220,7 @@

(defn- render-todo-list-query-settings [ list-id completed-within-days snoozed-for-days ]
[:div.query-settings
(form/form-to { :class "embedded "} [:get (shref "/list/" list-id)]
(hiccup-form/form-to { :class "embedded "} [:get (shref "/list/" list-id)]
[:div.control-segment
[:a {:href (shref "/list/" list-id {:view "completions"})}
"[recently completed]"]]
Expand All @@ -237,7 +239,7 @@

(defn- render-todo-list-completion-query-settings [ list-id completed-within-days ]
[:div.query-settings
(form/form-to { :class "embedded "} [:get (shref "/list/" list-id "/completions")]
(hiccup-form/form-to { :class "embedded "} [:get (shref "/list/" list-id "/completions")]
[:div.control-segment
[:a {:href (shref "/list/" list-id "/details")}
"[list details]"]]
Expand Down Expand Up @@ -306,7 +308,8 @@
[:h2
[:a
{:href (shref "/list/" (:sublist_id sublist-details))}
(:desc sublist-details)]]
(hiccup-util/escape-html
(:desc sublist-details))]]
items])))

(defn- render-todo-list-view [ list-id edit-item-id writable? completed-within-days snoozed-for-days ]
Expand Down Expand Up @@ -433,11 +436,13 @@

(defn- render-list-select [ id excluded-list-id ]
[:select { :id id :name id }
(form/select-options (map (fn [ list-info ]
[ (:desc list-info) (:todo_list_id list-info)])
(remove
#(= excluded-list-id (:todo_list_id %))
(data/get-todo-lists-by-user (auth/current-user-id)))))])
(hiccup-form/select-options
(map (fn [ list-info ]
[(hiccup-util/escape-html (:desc list-info))
(:todo_list_id list-info)])
(remove
#(= excluded-list-id (:todo_list_id %))
(data/get-todo-lists-by-user (auth/current-user-id)))))])

(defn render-update-from-modal [ params list-id ]
(render-modal
Expand Down
34 changes: 18 additions & 16 deletions src/toto/todo/todo_list_manager.clj
Expand Up @@ -28,7 +28,8 @@
toto.view.query
toto.view.page)
(:require [clojure.tools.logging :as log]
[hiccup.form :as form]
[hiccup.form :as hiccup-form]
[hiccup.util :as hiccup-util]
[toto.data.data :as data]
[toto.view.auth :as auth]
[toto.todo.sidebar-view :as sidebar-view]))
Expand All @@ -50,15 +51,15 @@
(list-priority-button list-id 0 img-arrow-blue)))

(defn render-new-list-form [ ]
(form/form-to
(hiccup-form/form-to
{:class "new-item-form"}
[:post (shref "/list")]
(form/text-field {:maxlength "32"
(hiccup-form/text-field {:maxlength "32"
:placeholder "New List Name"
:autofocus "autofocus"}
"list-description")
[:div
(form/check-box "is-view" false "Y")
(hiccup-form/check-box "is-view" false "Y")
[:label {:for "is-view"} "View"]]))

(defn render-list-list-page []
Expand Down Expand Up @@ -89,10 +90,10 @@
(defn- render-sort-list-panel [ list-id ]
[:div.config-panel
[:h1 "Sort List"]
(form/form-to {} [:post (shref "/list/" list-id "/sort")]
(hiccup-form/form-to {} [:post (shref "/list/" list-id "/sort")]
[:input {:type "submit" :value "Sort By"}]
[:select {:id "sort-by" :name "sort-by"}
(form/select-options [["Description" "desc"]
(hiccup-form/select-options [["Description" "desc"]
["Created Date" "created-on"]
["Updated Date" "updated-on"]
["Snoozed Until" "snoozed-until"]])])])
Expand All @@ -119,7 +120,7 @@
[:div.config-panel
[:h1 "List Permissions:"]
[:div
(form/check-box "is-public" (:is_public list-details))
(hiccup-form/check-box "is-public" (:is_public list-details))
[:label {:for "is-public"} "List publically visible?"]]]
[:div.config-panel
[:h1 "List Owners:"]
Expand All @@ -131,8 +132,8 @@
(if (= (auth/current-user-id) user-id)
[:div.self-owner
" "
(form/hidden-field user-parameter-name "on")]
(form/check-box user-parameter-name (in? list-owners user-id)))
(hiccup-form/hidden-field user-parameter-name "on")]
(hiccup-form/check-box user-parameter-name (in? list-owners user-id)))
[:label {:for user-parameter-name}
user-email-addr
(when (= (auth/current-user-id) user-id)
Expand All @@ -158,9 +159,10 @@
(map (fn [ todo-list ]
(let [ list-id (:todo_list_id todo-list) ]
[:div
(form/check-box (str "list_" list-id)
(in? view-sublist-ids list-id))
(:desc todo-list)]))
(hiccup-form/check-box (str "list_" list-id)
(in? view-sublist-ids list-id))
(hiccup-util/escape-html
(:desc todo-list))]))
(remove #(:is_view %) todo-lists))]]))

(defn render-todo-list-details-page [ list-id min-list-priority & { :keys [ error-message ]}]
Expand All @@ -169,19 +171,19 @@
is-view (:is_view list-details)
list-type (if is-view "View" "List")]
(render-page
{:title (str list-type " Details: " list-name)
{:title (str list-type " Details: " (hiccup-util/escape-html list-name))
:sidebar (sidebar-view/render-sidebar-list-list list-id min-list-priority 0)}
(scroll-column
'todo-list-details-column
[:h3
[:a { :href (str "/list/" list-id ) } img-back-arrow]
"List Details: " list-name]
(form/form-to
"List Details: " (hiccup-util/escape-html list-name)]
(hiccup-form/form-to
{:class "details"}
[:post (shref "/list/" list-id "/details")]
[:div.config-panel
[:h1 (str list-type " Name:")]
(form/text-field { :maxlength "32" } "list-name" list-name)]
(hiccup-form/text-field { :maxlength "32" } "list-name" list-name)]
(if is-view
(render-todo-list-view-editor list-id)
(render-todo-list-permissions list-id error-message))
Expand Down
23 changes: 12 additions & 11 deletions src/toto/view/page.clj
Expand Up @@ -27,8 +27,9 @@
toto.view.query
toto.view.components)
(:require [clojure.tools.logging :as log]
[hiccup.page :as page]
[hiccup.form :as form]
[hiccup.page :as hiccup-page]
[hiccup.form :as hiccup-form]
[hiccup.util :as hiccup-util]
[toto.view.auth :as auth]))

(defn session-controls []
Expand All @@ -54,7 +55,7 @@
[:div.cancel
[:a {:href escape-url} img-window-close]]
(if-let [ form-post-to (:form-post-to attrs)]
(form/form-to [:post form-post-to] contents)
(hiccup-form/form-to [:post form-post-to] contents)
contents)]]))

(defn- render-support-modal [ ]
Expand All @@ -64,25 +65,25 @@
:form-post-to "/support-message"}
[:div.config-panel
[:h1 "Contact Information"]
(form/text-field {:maxlength "128"
(hiccup-form/text-field {:maxlength "128"
:placeholder "Full Name"
:autocomplete "off"
:autofocus "on"}
"full-name")
(form/text-field (cond-> {:maxlength "128"
(hiccup-form/text-field (cond-> {:maxlength "128"
:placeholder "E-Mail Address"
:value user-identity}
user-identity (assoc :readonly "readonly"))
"email-address")]
(render-verify-question)
[:div.config-panel
[:h1 "Message"]
(form/text-area {:maxlength "4096"
(hiccup-form/text-area {:maxlength "4096"
:rows "12"
:cols "64"
:autocomplete "off"}
"message-text")]
(form/hidden-field "current-uri" (shref))
(hiccup-form/hidden-field "current-uri" (shref))
[:input {:type "submit" :value "Send Message"}])))

(defn contact-support-button [ ]
Expand All @@ -95,10 +96,10 @@
:content "width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0"}]
[:title (when *dev-mode* "DEV - ") (:name (:app *config*)) (when title (str " - " title))]
[:link { :rel "shortcut icon" :href (resource "favicon.ico")}]
(page/include-css (resource "toto.css")
(hiccup-page/include-css (resource "toto.css")
(resource "font-awesome.min.css"))
[:script {:type "module" :src (resource "toto.js")}]
(page/include-js (resource "DragDropTouch.js"))])
(hiccup-page/include-js (resource "DragDropTouch.js"))])

(defn- render-header [ page-title show-menu? ]
(let [ username (auth/current-identity)]
Expand All @@ -107,7 +108,7 @@
[:span.toggle-menu img-show-list " "])
[:span.app-name
[:a { :href "/" } (:name (:app *config*))] " - "]
page-title
(hiccup-util/escape-html page-title)
(when *dev-mode*
[:span.pill.dev "DEV"])
(session-controls)]))
Expand Down Expand Up @@ -149,7 +150,7 @@
contents]]))

(defn render-page [ attrs & contents]
(page/html5
(hiccup-page/html5
[:html
(render-standard-header (:title attrs))
(render-page-body attrs contents)]))

0 comments on commit fdc825a

Please sign in to comment.