diff --git a/app/controllers/users/invitations_controller.rb b/app/controllers/users/invitations_controller.rb
index bac1b5707..b9a7cee5f 100644
--- a/app/controllers/users/invitations_controller.rb
+++ b/app/controllers/users/invitations_controller.rb
@@ -175,8 +175,8 @@ module Users
message = "#{I18n.t('search.index.team')} #{team.name}"
notification = Notification.create(
type_of: :assignment,
- title: ActionController::Base.helpers.sanitize(title),
- message: ActionController::Base.helpers.sanitize(message)
+ title: InputSanitizeHelper.sanitize_inpute(title),
+ message: InputSanitizeHelper.sanitize_input(message)
)
if target_user.assignments_notification
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index cf037686a..0e10f8071 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -92,10 +92,8 @@ module ApplicationHelper
def generate_annotation_notification(target_user, title, message)
notification = Notification.create(
type_of: :assignment,
- title:
- ActionController::Base.helpers.sanitize(title),
- message:
- ActionController::Base.helpers.sanitize(message)
+ title: sanitize_input(title),
+ message: sanitize_input(message)
)
if target_user.assignments_notification
UserNotification.create(notification: notification, user: target_user)
@@ -122,11 +120,13 @@ module ApplicationHelper
project = Project.find_by_id(match[3].base62_decode)
next unless project
if project.archived?
- "#{sanitize(match[2])} " \
+ "" \
+ "#{sanitize_input(match[2])} " \
"#{link_to project.name,
projects_archive_path} #{I18n.t('atwho.res.archived')}"
else
- "#{sanitize(match[2])} " \
+ "" \
+ "#{sanitize_input(match[2])} " \
"#{link_to project.name,
project_path(project)}"
end
@@ -134,12 +134,14 @@ module ApplicationHelper
experiment = Experiment.find_by_id(match[3].base62_decode)
next unless experiment
if experiment.archived?
- "#{sanitize(match[2])} " \
+ "" \
+ "#{sanitize_input(match[2])} " \
"#{link_to experiment.name,
experiment_archive_project_path(experiment.project)} " \
"#{I18n.t('atwho.res.archived')}"
else
- "#{sanitize(match[2])} " \
+ ""\
+ "#{sanitize_input(match[2])} " \
"#{link_to experiment.name,
canvas_experiment_path(experiment)}"
end
@@ -147,12 +149,14 @@ module ApplicationHelper
my_module = MyModule.find_by_id(match[3].base62_decode)
next unless my_module
if my_module.archived?
- "#{sanitize(match[2])} " \
+ "" \
+ "#{sanitize_input(match[2])} " \
"#{link_to my_module.name,
module_archive_experiment_path(my_module.experiment)} " \
"#{I18n.t('atwho.res.archived')}"
else
- "#{sanitize(match[2])} " \
+ "" \
+ "#{sanitize_input(match[2])} " \
"#{link_to my_module.name,
protocols_my_module_path(my_module)}"
end
diff --git a/app/helpers/input_sanitize_helper.rb b/app/helpers/input_sanitize_helper.rb
index 6b038e3ec..b8ba5b5d6 100644
--- a/app/helpers/input_sanitize_helper.rb
+++ b/app/helpers/input_sanitize_helper.rb
@@ -5,12 +5,13 @@ module InputSanitizeHelper
# the ActiveRecord connecton method on the caller object which in
# our cases throws an error when called from not ActiveRecord objects
# such as SamplesDatatables
- def sanitize_input(text, tags = [], attributes = [])
+ def sanitize_input(html, tags = [], attributes = [])
Sanitize.fragment(
- text,
+ html,
elements: Constants::WHITELISTED_TAGS + tags,
- attributes: { all: Constants::WHITELISTED_ATTRIBUTES + attributes }
- )
+ attributes: { all: Constants::WHITELISTED_ATTRIBUTES + attributes },
+ css: Constants::WHITELISTED_CSS_ATTRIBUTES
+ ).html_safe
end
def escape_input(text)
@@ -22,9 +23,9 @@ module InputSanitizeHelper
team = options.fetch(:team) { nil }
wrapper_tag = options.fetch(:wrapper_tag) { {} }
tags = options.fetch(:tags) { [] }
- fromat_opt = wrapper_tag.merge(sanitize: false)
+ format_opt = wrapper_tag.merge(sanitize: false)
text = sanitize_input(text, tags)
- text = simple_format(sanitize_input(text), {}, fromat_opt) if simple_f
+ text = simple_format(sanitize_input(text), {}, format_opt) if simple_f
auto_link(
smart_annotation_parser(text, team),
link: :urls,
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index e21066a54..f41eb90ac 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -40,10 +40,8 @@ module NotificationsHelper
notification = Notification.create(
type_of: :assignment,
- title:
- ActionController::Base.helpers.sanitize(title),
- message:
- ActionController::Base.helpers.sanitize(message)
+ title: sanitize_input(title),
+ message: sanitize_input(message)
)
if target_user.assignments_notification
diff --git a/app/models/activity.rb b/app/models/activity.rb
index 47541a78f..e0768d43f 100644
--- a/app/models/activity.rb
+++ b/app/models/activity.rb
@@ -104,15 +104,12 @@ class Activity < ActiveRecord::Base
notification = Notification.create(
type_of: notification_type,
- title:
- ActionController::Base.helpers.sanitize(message, tags: %w(strong a)),
- message:
- ActionController::Base
- .helpers.sanitize(
- "#{I18n.t('search.index.project')}
- #{project_m} #{experiment_m} #{task_m}",
- tags: %w(strong a)
- ),
+ title: InputSanitizeHelper.sanitize_input(message, tags: %w(strong a)),
+ message: InputSanitizeHelper.sanitize_input(
+ "#{I18n.t('search.index.project')}
+ #{project_m} #{experiment_m} #{task_m}",
+ tags: %w(strong a)
+ ),
generator_user_id: user.id
)
diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb
index 3b48409e1..c91632ac8 100644
--- a/config/initializers/constants.rb
+++ b/config/initializers/constants.rb
@@ -222,8 +222,643 @@ class Constants
WHITELISTED_ATTRIBUTES = %w(
href src width height alt cite datetime title class name xml:lang abbr style
+ target data-*
).freeze
+ WHITELISTED_CSS_ATTRIBUTES = {
+ allow_comments: false,
+ allow_hacks: false,
+ at_rules_with_properties: %w[
+ bottom-center bottom-left bottom-left-corner bottom-right
+ bottom-right-corner font-face left-bottom left-middle left-top page
+ right-bottom right-middle right-top top-center top-left
+ top-left-corner top-right top-right-corner
+ ],
+ at_rules_with_styles: %w[
+ -moz-keyframes -o-keyframes -webkit-keyframes document
+ keyframes media supports
+ ],
+ protocols: ['http', 'https', :relative],
+ properties: %w[
+ -moz-appearance
+ -moz-background-inline-policy
+ -moz-box-sizing
+ -moz-column-count
+ -moz-column-fill
+ -moz-column-gap
+ -moz-column-rule
+ -moz-column-rule-color
+ -moz-column-rule-style
+ -moz-column-rule-width
+ -moz-column-width
+ -moz-font-feature-settings
+ -moz-font-language-override
+ -moz-hyphens
+ -moz-text-align-last
+ -moz-text-decoration-color
+ -moz-text-decoration-line
+ -moz-text-decoration-style
+ -moz-text-size-adjust
+ -ms-background-position-x
+ -ms-background-position-y
+ -ms-block-progression
+ -ms-content-zoom-chaining
+ -ms-content-zoom-limit
+ -ms-content-zoom-limit-max
+ -ms-content-zoom-limit-min
+ -ms-content-zoom-snap
+ -ms-content-zoom-snap-points
+ -ms-content-zoom-snap-type
+ -ms-content-zooming
+ -ms-filter
+ -ms-flex
+ -ms-flex-align
+ -ms-flex-direction
+ -ms-flex-order
+ -ms-flex-pack
+ -ms-flex-wrap
+ -ms-flow-from
+ -ms-flow-into
+ -ms-grid-column
+ -ms-grid-column-align
+ -ms-grid-column-span
+ -ms-grid-columns
+ -ms-grid-row
+ -ms-grid-row-align
+ -ms-grid-row-span
+ -ms-grid-rows
+ -ms-high-contrast-adjust
+ -ms-hyphenate-limit-chars
+ -ms-hyphenate-limit-lines
+ -ms-hyphenate-limit-zone
+ -ms-hyphens
+ -ms-ime-mode
+ -ms-interpolation-mode
+ -ms-layout-flow
+ -ms-layout-grid
+ -ms-layout-grid-char
+ -ms-layout-grid-line
+ -ms-layout-grid-mode
+ -ms-layout-grid-type
+ -ms-overflow-style
+ -ms-overflow-x
+ -ms-overflow-y
+ -ms-progress-appearance
+ -ms-scroll-chaining
+ -ms-scroll-limit
+ -ms-scroll-limit-x-max
+ -ms-scroll-limit-x-min
+ -ms-scroll-limit-y-max
+ -ms-scroll-limit-y-min
+ -ms-scroll-rails
+ -ms-scroll-snap-points-x
+ -ms-scroll-snap-points-y
+ -ms-scroll-snap-type
+ -ms-scroll-snap-x
+ -ms-scroll-snap-y
+ -ms-scroll-translation
+ -ms-scrollbar-arrow-color
+ -ms-scrollbar-base-color
+ -ms-scrollbar-darkshadow-color
+ -ms-scrollbar-face-color
+ -ms-scrollbar-highlight-color
+ -ms-scrollbar-shadow-color
+ -ms-scrollbar-track-color
+ -ms-text-align-last
+ -ms-text-autospace
+ -ms-text-justify
+ -ms-text-kashida-space
+ -ms-text-overflow
+ -ms-text-size-adjust
+ -ms-text-underline-position
+ -ms-touch-action
+ -ms-user-select
+ -ms-word-break
+ -ms-word-wrap
+ -ms-wrap-flow
+ -ms-wrap-margin
+ -ms-wrap-through
+ -ms-writing-mode
+ -ms-zoom
+ -webkit-align-content
+ -webkit-align-items
+ -webkit-align-self
+ -webkit-animation
+ -webkit-animation-delay
+ -webkit-animation-direction
+ -webkit-animation-duration
+ -webkit-animation-fill-mode
+ -webkit-animation-iteration-count
+ -webkit-animation-name
+ -webkit-animation-play-state
+ -webkit-animation-timing-function
+ -webkit-appearance
+ -webkit-backface-visibility
+ -webkit-background-blend-mode
+ -webkit-background-clip
+ -webkit-background-composite
+ -webkit-background-origin
+ -webkit-background-size
+ -webkit-blend-mode
+ -webkit-border-after
+ -webkit-border-after-color
+ -webkit-border-after-style
+ -webkit-border-after-width
+ -webkit-border-before
+ -webkit-border-before-color
+ -webkit-border-before-style
+ -webkit-border-before-width
+ -webkit-border-bottom-left-radius
+ -webkit-border-bottom-right-radius
+ -webkit-border-end
+ -webkit-border-end-color
+ -webkit-border-end-style
+ -webkit-border-end-width
+ -webkit-border-fit
+ -webkit-border-image
+ -webkit-border-radius
+ -webkit-border-start
+ -webkit-border-start-color
+ -webkit-border-start-style
+ -webkit-border-start-width
+ -webkit-border-top-left-radius
+ -webkit-border-top-right-radius
+ -webkit-box-align
+ -webkit-box-decoration-break
+ -webkit-box-flex
+ -webkit-box-flex-group
+ -webkit-box-lines
+ -webkit-box-ordinal-group
+ -webkit-box-orient
+ -webkit-box-pack
+ -webkit-box-reflect
+ -webkit-box-shadow
+ -webkit-box-sizing
+ -webkit-clip-path
+ -webkit-column-axis
+ -webkit-column-break-after
+ -webkit-column-break-before
+ -webkit-column-break-inside
+ -webkit-column-count
+ -webkit-column-gap
+ -webkit-column-progression
+ -webkit-column-rule
+ -webkit-column-rule-color
+ -webkit-column-rule-style
+ -webkit-column-rule-width
+ -webkit-column-span
+ -webkit-column-width
+ -webkit-columns
+ -webkit-filter
+ -webkit-flex
+ -webkit-flex-basis
+ -webkit-flex-direction
+ -webkit-flex-flow
+ -webkit-flex-grow
+ -webkit-flex-shrink
+ -webkit-flex-wrap
+ -webkit-flow-from
+ -webkit-flow-into
+ -webkit-font-size-delta
+ -webkit-font-smoothing
+ -webkit-grid-area
+ -webkit-grid-auto-columns
+ -webkit-grid-auto-flow
+ -webkit-grid-auto-rows
+ -webkit-grid-column
+ -webkit-grid-column-end
+ -webkit-grid-column-start
+ -webkit-grid-definition-columns
+ -webkit-grid-definition-rows
+ -webkit-grid-row
+ -webkit-grid-row-end
+ -webkit-grid-row-start
+ -webkit-justify-content
+ -webkit-line-clamp
+ -webkit-logical-height
+ -webkit-logical-width
+ -webkit-margin-after
+ -webkit-margin-after-collapse
+ -webkit-margin-before
+ -webkit-margin-before-collapse
+ -webkit-margin-bottom-collapse
+ -webkit-margin-collapse
+ -webkit-margin-end
+ -webkit-margin-start
+ -webkit-margin-top-collapse
+ -webkit-marquee
+ -webkit-marquee-direction
+ -webkit-marquee-increment
+ -webkit-marquee-repetition
+ -webkit-marquee-speed
+ -webkit-marquee-style
+ -webkit-mask
+ -webkit-mask-box-image
+ -webkit-mask-box-image-outset
+ -webkit-mask-box-image-repeat
+ -webkit-mask-box-image-slice
+ -webkit-mask-box-image-source
+ -webkit-mask-box-image-width
+ -webkit-mask-clip
+ -webkit-mask-composite
+ -webkit-mask-image
+ -webkit-mask-origin
+ -webkit-mask-position
+ -webkit-mask-position-x
+ -webkit-mask-position-y
+ -webkit-mask-repeat
+ -webkit-mask-repeat-x
+ -webkit-mask-repeat-y
+ -webkit-mask-size
+ -webkit-mask-source-type
+ -webkit-max-logical-height
+ -webkit-max-logical-width
+ -webkit-min-logical-height
+ -webkit-min-logical-width
+ -webkit-opacity
+ -webkit-order
+ -webkit-padding-after
+ -webkit-padding-before
+ -webkit-padding-end
+ -webkit-padding-start
+ -webkit-perspective
+ -webkit-perspective-origin
+ -webkit-perspective-origin-x
+ -webkit-perspective-origin-y
+ -webkit-region-break-after
+ -webkit-region-break-before
+ -webkit-region-break-inside
+ -webkit-region-fragment
+ -webkit-shape-inside
+ -webkit-shape-margin
+ -webkit-shape-outside
+ -webkit-shape-padding
+ -webkit-svg-shadow
+ -webkit-tap-highlight-color
+ -webkit-text-decoration
+ -webkit-text-decoration-color
+ -webkit-text-decoration-line
+ -webkit-text-decoration-style
+ -webkit-text-size-adjust
+ -webkit-touch-callout
+ -webkit-transform
+ -webkit-transform-origin
+ -webkit-transform-origin-x
+ -webkit-transform-origin-y
+ -webkit-transform-origin-z
+ -webkit-transform-style
+ -webkit-transition
+ -webkit-transition-delay
+ -webkit-transition-duration
+ -webkit-transition-property
+ -webkit-transition-timing-function
+ -webkit-user-drag
+ -webkit-wrap-flow
+ -webkit-wrap-through
+ align-content
+ align-items
+ align-self
+ alignment-adjust
+ alignment-baseline
+ all
+ anchor-point
+ animation
+ animation-delay
+ animation-direction
+ animation-duration
+ animation-fill-mode
+ animation-iteration-count
+ animation-name
+ animation-play-state
+ animation-timing-function
+ azimuth
+ backface-visibility
+ background
+ background-attachment
+ background-clip
+ background-color
+ background-image
+ background-origin
+ background-position
+ background-repeat
+ background-size
+ baseline-shift
+ binding
+ bleed
+ bookmark-label
+ bookmark-level
+ bookmark-state
+ border
+ border-bottom
+ border-bottom-color
+ border-bottom-left-radius
+ border-bottom-right-radius
+ border-bottom-style
+ border-bottom-width
+ border-collapse
+ border-color
+ border-image
+ border-image-outset
+ border-image-repeat
+ border-image-slice
+ border-image-source
+ border-image-width
+ border-left
+ border-left-color
+ border-left-style
+ border-left-width
+ border-radius
+ border-right
+ border-right-color
+ border-right-style
+ border-right-width
+ border-spacing
+ border-style
+ border-top
+ border-top-color
+ border-top-left-radius
+ border-top-right-radius
+ border-top-style
+ border-top-width
+ border-width
+ bottom
+ box-decoration-break
+ box-shadow
+ box-sizing
+ box-snap
+ box-suppress
+ break-after
+ break-before
+ break-inside
+ caption-side
+ chains
+ clear
+ clip
+ clip-path
+ clip-rule
+ color
+ color-interpolation-filters
+ column-count
+ column-fill
+ column-gap
+ column-rule
+ column-rule-color
+ column-rule-style
+ column-rule-width
+ column-span
+ column-width
+ columns
+ contain
+ content
+ counter-increment
+ counter-reset
+ counter-set
+ crop
+ cue
+ cue-after
+ cue-before
+ cursor
+ direction
+ display
+ display-inside
+ display-list
+ display-outside
+ dominant-baseline
+ elevation
+ empty-cells
+ filter
+ flex
+ flex-basis
+ flex-direction
+ flex-flow
+ flex-grow
+ flex-shrink
+ flex-wrap
+ float
+ float-offset
+ flood-color
+ flood-opacity
+ flow-from
+ flow-into
+ font
+ font-family
+ font-feature-settings
+ font-kerning
+ font-language-override
+ font-size
+ font-size-adjust
+ font-stretch
+ font-style
+ font-synthesis
+ font-variant
+ font-variant-alternates
+ font-variant-caps
+ font-variant-east-asian
+ font-variant-ligatures
+ font-variant-numeric
+ font-variant-position
+ font-weight
+ grid
+ grid-area
+ grid-auto-columns
+ grid-auto-flow
+ grid-auto-rows
+ grid-column
+ grid-column-end
+ grid-column-start
+ grid-row
+ grid-row-end
+ grid-row-start
+ grid-template
+ grid-template-areas
+ grid-template-columns
+ grid-template-rows
+ hanging-punctuation
+ height
+ hyphens
+ icon
+ image-orientation
+ image-rendering
+ image-resolution
+ ime-mode
+ initial-letters
+ inline-box-align
+ justify-content
+ justify-items
+ justify-self
+ left
+ letter-spacing
+ lighting-color
+ line-box-contain
+ line-break
+ line-grid
+ line-height
+ line-snap
+ line-stacking
+ line-stacking-ruby
+ line-stacking-shift
+ line-stacking-strategy
+ list-style
+ list-style-image
+ list-style-position
+ list-style-type
+ margin
+ margin-bottom
+ margin-left
+ margin-right
+ margin-top
+ marker-offset
+ marker-side
+ marks
+ mask
+ mask-box
+ mask-box-outset
+ mask-box-repeat
+ mask-box-slice
+ mask-box-source
+ mask-box-width
+ mask-clip
+ mask-image
+ mask-origin
+ mask-position
+ mask-repeat
+ mask-size
+ mask-source-type
+ mask-type
+ max-height
+ max-lines
+ max-width
+ min-height
+ min-width
+ move-to
+ nav-down
+ nav-index
+ nav-left
+ nav-right
+ nav-up
+ object-fit
+ object-position
+ opacity
+ order
+ orphans
+ outline
+ outline-color
+ outline-offset
+ outline-style
+ outline-width
+ overflow
+ overflow-wrap
+ overflow-x
+ overflow-y
+ padding
+ padding-bottom
+ padding-left
+ padding-right
+ padding-top
+ page
+ page-break-after
+ page-break-before
+ page-break-inside
+ page-policy
+ pause
+ pause-after
+ pause-before
+ perspective
+ perspective-origin
+ pitch
+ pitch-range
+ play-during
+ position
+ presentation-level
+ quotes
+ region-fragment
+ resize
+ rest
+ rest-after
+ rest-before
+ richness
+ right
+ rotation
+ rotation-point
+ ruby-align
+ ruby-merge
+ ruby-position
+ shape-image-threshold
+ shape-margin
+ shape-outside
+ size
+ speak
+ speak-as
+ speak-header
+ speak-numeral
+ speak-punctuation
+ speech-rate
+ stress
+ string-set
+ tab-size
+ table-layout
+ text-align
+ text-align-last
+ text-combine-horizontal
+ text-combine-upright
+ text-decoration
+ text-decoration-color
+ text-decoration-line
+ text-decoration-skip
+ text-decoration-style
+ text-emphasis
+ text-emphasis-color
+ text-emphasis-position
+ text-emphasis-style
+ text-height
+ text-indent
+ text-justify
+ text-orientation
+ text-overflow
+ text-rendering
+ text-shadow
+ text-size-adjust
+ text-space-collapse
+ text-transform
+ text-underline-position
+ text-wrap
+ top
+ touch-action
+ transform
+ transform-origin
+ transform-style
+ transition
+ transition-delay
+ transition-duration
+ transition-property
+ transition-timing-function
+ unicode-bidi
+ unicode-range
+ vertical-align
+ visibility
+ voice-balance
+ voice-duration
+ voice-family
+ voice-pitch
+ voice-range
+ voice-rate
+ voice-stress
+ voice-volume
+ volume
+ white-space
+ widows
+ width
+ will-change
+ word-break
+ word-spacing
+ word-wrap
+ wrap-flow
+ wrap-through
+ writing-mode
+ z-index
+ ]
+ }.freeze
+
EXPORTABLE_ZIP_EXPIRATION_DAYS = 7
# Very basic regex to check for validity of emails