diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
index 229457f96..b6b1a57f6 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee
@@ -132,7 +132,10 @@ class App.TicketZoomArticleNew extends App.Controller
textRange.select()
isIE10: ->
- Function('/*@cc_on return document.documentMode===10@*/')()
+ detected = App.Browser.detection()
+ return false if !detected.browser
+ return false if detected.browser.name != 'Explorer'
+ return detected.browser.major == 10
release: =>
if @subscribeIdTextModule
diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
index aac1dc3ea..d83e03dff 100644
--- a/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
+++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_view.coffee
@@ -134,7 +134,12 @@ class ArticleViewItem extends App.ObserverController
attachments = App.TicketArticle.contentAttachments(article)
if article.attachments
for attachment in article.attachments
- attachment.url = "#{App.Config.get('api_path')}/ticket_attachment/#{article.ticket_id}/#{article.id}/#{attachment.id}?disposition=attachment"
+
+ dispositionParams = ''
+ if attachment?.preferences['Content-Type'] isnt 'application/pdf' && attachment?.preferences['Content-Type'] isnt 'text/html'
+ dispositionParams = '?disposition=attachment'
+
+ attachment.url = "#{App.Config.get('api_path')}/ticket_attachment/#{article.ticket_id}/#{article.id}/#{attachment.id}#{dispositionParams}"
attachment.preview_url = "#{App.Config.get('api_path')}/ticket_attachment/#{article.ticket_id}/#{article.id}/#{attachment.id}?view=preview"
if attachment && attachment.preferences && attachment.preferences['original-format'] is true
diff --git a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee
index b49757943..b80fb772e 100644
--- a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee
+++ b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee
@@ -47,6 +47,33 @@ class Widget extends App.Controller
# enable translation inline
App.Config.set('translation_inline', true)
+ @observer = new MutationObserver((mutations) ->
+
+ mutations.forEach((mutation) ->
+
+ mutation.addedNodes.forEach((addedNode) ->
+
+ $(addedNode).find('span.translation').on('click.translation', (e) ->
+ e.stopPropagation()
+ return false
+ )
+ $(addedNode).find('span.translation').on('keydown.translation', (e) ->
+ e.stopPropagation()
+ return true
+ )
+ )
+
+ mutation.removedNodes.forEach((removedNode) ->
+ $(removedNode).find('span.translation').off('.translation')
+ )
+ )
+ )
+
+ @observer.observe(document.body, {
+ subtree: true,
+ childList: true,
+ })
+
# rerender controllers
App.Event.trigger('ui:rerender')
@@ -93,7 +120,9 @@ class Widget extends App.Controller
element
disable: ->
- $('body').off('focus.translation blur.translation')
+ @observer.disconnect()
+
+ $('body').off('.translation')
# disable translation inline
App.Config.set('translation_inline', false)
diff --git a/app/assets/javascripts/app/lib/app_post/i18n.coffee b/app/assets/javascripts/app/lib/app_post/i18n.coffee
index 3d5e50476..d3328c086 100644
--- a/app/assets/javascripts/app/lib/app_post/i18n.coffee
+++ b/app/assets/javascripts/app/lib/app_post/i18n.coffee
@@ -247,7 +247,7 @@ class _i18nSingleton extends Spine.Module
return string if !string
if App.Config.get('translation_inline')
- return '' + App.Utils.htmlEscape(@translate(string)) + ''
+ return '' + App.Utils.htmlEscape(@translate(string)) + ''
translated = @translate(string, args, true, true)
diff --git a/app/assets/javascripts/app/lib/mixins/view_helpers.coffee b/app/assets/javascripts/app/lib/mixins/view_helpers.coffee
index e10f34de9..213aba1be 100644
--- a/app/assets/javascripts/app/lib/mixins/view_helpers.coffee
+++ b/app/assets/javascripts/app/lib/mixins/view_helpers.coffee
@@ -193,6 +193,7 @@ App.ViewHelpers =
canDownload: (contentType) ->
contentType = App.Utils.contentTypeCleanup(contentType)
+ return false if contentType is 'application/pdf'
contentType != 'text/html'
canPreview: (contentType) ->
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index c5b173773..c0bfab08f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
include ApplicationController::HasUser
include ApplicationController::HasResponseExtentions
include ApplicationController::PreventsCsrf
+ include ApplicationController::HasSecureContentSecurityPolicyForDownloads
include ApplicationController::LogsHttpAccess
include ApplicationController::ChecksAccess
end
diff --git a/app/controllers/application_controller/has_secure_content_security_policy_for_downloads.rb b/app/controllers/application_controller/has_secure_content_security_policy_for_downloads.rb
new file mode 100644
index 000000000..c1e5896b5
--- /dev/null
+++ b/app/controllers/application_controller/has_secure_content_security_policy_for_downloads.rb
@@ -0,0 +1,23 @@
+module ApplicationController::HasSecureContentSecurityPolicyForDownloads
+ extend ActiveSupport::Concern
+
+ included do
+
+ around_action do |_controller, block|
+
+ subscriber = proc do
+ policy = ActionDispatch::ContentSecurityPolicy.new
+ policy.default_src :none
+ policy.plugin_types 'application/pdf'
+
+ request.content_security_policy = policy
+ end
+
+ ActiveSupport::Notifications.subscribed(subscriber, 'send_file.action_controller') do
+ ActiveSupport::Notifications.subscribed(subscriber, 'send_data.action_controller') do
+ block.call
+ end
+ end
+ end
+ end
+end
diff --git a/app/views/init/index.html.erb b/app/views/init/index.html.erb
index 30d905a1a..67f2dfe75 100644
--- a/app/views/init/index.html.erb
+++ b/app/views/init/index.html.erb
@@ -1,5 +1,5 @@
-
+<% end -%>
\ No newline at end of file
+
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 013044b09..4fc68adfc 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -9,9 +9,9 @@
<%= stylesheet_link_tag "application", :media => 'all' %>
<%= stylesheet_link_tag "application-print", :media => 'print' %>
<% if Rails.configuration.assets.debug %>
- <%= javascript_include_tag "application" %>
+ <%= javascript_include_tag "application", nonce: true %>
<% else %>
- <%= javascript_include_tag "application", :defer => 'defer' %>
+ <%= javascript_include_tag "application", nonce: true, :defer => 'defer' %>
<% end %>
<%= csrf_meta_tags %>
diff --git a/app/views/layouts/knowledge_base.html.erb b/app/views/layouts/knowledge_base.html.erb
index 4e880272c..351f822f7 100644
--- a/app/views/layouts/knowledge_base.html.erb
+++ b/app/views/layouts/knowledge_base.html.erb
@@ -70,10 +70,13 @@
-
+<% end -%>
-<%= javascript_include_tag 'knowledge_base_public' %>
+<%= javascript_include_tag 'knowledge_base_public', nonce: true %>
diff --git a/app/views/tests/color_object.html.erb b/app/views/tests/color_object.html.erb
index 410d26775..4ee602d32 100644
--- a/app/views/tests/color_object.html.erb
+++ b/app/views/tests/color_object.html.erb
@@ -1,7 +1,5 @@
-
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/color_object.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/core.html.erb b/app/views/tests/core.html.erb
index 81fee2c0c..c702f8a88 100644
--- a/app/views/tests/core.html.erb
+++ b/app/views/tests/core.html.erb
@@ -1,7 +1,5 @@
-
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/core.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form.html.erb b/app/views/tests/form.html.erb
index cc8cdf5fa..8cfcddffc 100644
--- a/app/views/tests/form.html.erb
+++ b/app/views/tests/form.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_color.html.erb b/app/views/tests/form_color.html.erb
index b10567c10..9cfc4d668 100644
--- a/app/views/tests/form_color.html.erb
+++ b/app/views/tests/form_color.html.erb
@@ -1,8 +1,5 @@
-
-
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/syn-0.14.1.js", "/assets/tests/form_color.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_column_select.html.erb b/app/views/tests/form_column_select.html.erb
index fd85f7149..5ec2e2227 100644
--- a/app/views/tests/form_column_select.html.erb
+++ b/app/views/tests/form_column_select.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_column_select.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_extended.html.erb b/app/views/tests/form_extended.html.erb
index 9875c64a5..42938d319 100644
--- a/app/views/tests/form_extended.html.erb
+++ b/app/views/tests/form_extended.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_extended.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_find.html.erb b/app/views/tests/form_find.html.erb
index 7e9c41697..0e2ab5fa3 100644
--- a/app/views/tests/form_find.html.erb
+++ b/app/views/tests/form_find.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_find.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_searchable_select.html.erb b/app/views/tests/form_searchable_select.html.erb
index 57ad2d60e..370046bfc 100644
--- a/app/views/tests/form_searchable_select.html.erb
+++ b/app/views/tests/form_searchable_select.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_searchable_select.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_ticket_perform_action.html.erb b/app/views/tests/form_ticket_perform_action.html.erb
index 2248bd106..e7c26d10a 100644
--- a/app/views/tests/form_ticket_perform_action.html.erb
+++ b/app/views/tests/form_ticket_perform_action.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_ticket_perform_action.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_timer.html.erb b/app/views/tests/form_timer.html.erb
index 5e9a1eaad..7a425a1c2 100644
--- a/app/views/tests/form_timer.html.erb
+++ b/app/views/tests/form_timer.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_timer.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_tree_select.html.erb b/app/views/tests/form_tree_select.html.erb
index 15fadf932..10252b9b0 100644
--- a/app/views/tests/form_tree_select.html.erb
+++ b/app/views/tests/form_tree_select.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_tree_select.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_trim.html.erb b/app/views/tests/form_trim.html.erb
index fdb50b0d2..53ce96ad3 100644
--- a/app/views/tests/form_trim.html.erb
+++ b/app/views/tests/form_trim.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_trim.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/form_validation.html.erb b/app/views/tests/form_validation.html.erb
index 19e688d01..0595cb3c4 100644
--- a/app/views/tests/form_validation.html.erb
+++ b/app/views/tests/form_validation.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_validation.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
@@ -19,4 +18,4 @@ body {
-
\ No newline at end of file
+
diff --git a/app/views/tests/html_utils.html.erb b/app/views/tests/html_utils.html.erb
index 97cadc26b..c5faea044 100644
--- a/app/views/tests/html_utils.html.erb
+++ b/app/views/tests/html_utils.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/html_utils.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/i18n.html.erb b/app/views/tests/i18n.html.erb
index 6ff3e0590..ba8e3a65e 100644
--- a/app/views/tests/i18n.html.erb
+++ b/app/views/tests/i18n.html.erb
@@ -1,6 +1,5 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/i18n.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/local_storage.html.erb b/app/views/tests/local_storage.html.erb
index 298aee419..68f65a404 100644
--- a/app/views/tests/local_storage.html.erb
+++ b/app/views/tests/local_storage.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/local_storage.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/model.html.erb b/app/views/tests/model.html.erb
index 90e1e1d37..d418fa133 100644
--- a/app/views/tests/model.html.erb
+++ b/app/views/tests/model.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/model_binding.html.erb b/app/views/tests/model_binding.html.erb
index 4748a1f1b..a1ca3713e 100644
--- a/app/views/tests/model_binding.html.erb
+++ b/app/views/tests/model_binding.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_binding.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/model_ticket.html.erb b/app/views/tests/model_ticket.html.erb
index 71b64d95a..27166aa42 100644
--- a/app/views/tests/model_ticket.html.erb
+++ b/app/views/tests/model_ticket.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_ticket.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/model_ui.html.erb b/app/views/tests/model_ui.html.erb
index 32070b1dc..7aa4f623c 100644
--- a/app/views/tests/model_ui.html.erb
+++ b/app/views/tests/model_ui.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_ui.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/session.html.erb b/app/views/tests/session.html.erb
index 14b83ecec..ae886f8c6 100644
--- a/app/views/tests/session.html.erb
+++ b/app/views/tests/session.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/session.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/table.html.erb b/app/views/tests/table.html.erb
index 6e6a4d6b8..b275c5d83 100644
--- a/app/views/tests/table.html.erb
+++ b/app/views/tests/table.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/table.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
-
\ No newline at end of file
+
diff --git a/app/views/tests/table_extended.html.erb b/app/views/tests/table_extended.html.erb
index eefb9c49e..c206be011 100644
--- a/app/views/tests/table_extended.html.erb
+++ b/app/views/tests/table_extended.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/table_extended.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
-
\ No newline at end of file
+
diff --git a/app/views/tests/taskbar.html.erb b/app/views/tests/taskbar.html.erb
index 3402a378a..74ec95b60 100644
--- a/app/views/tests/taskbar.html.erb
+++ b/app/views/tests/taskbar.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/taskbar.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/text_module.html.erb b/app/views/tests/text_module.html.erb
index e41a8208d..dbfca44a9 100644
--- a/app/views/tests/text_module.html.erb
+++ b/app/views/tests/text_module.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/text_module.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/ticket_selector.html.erb b/app/views/tests/ticket_selector.html.erb
index 36f67335f..a00908d02 100644
--- a/app/views/tests/ticket_selector.html.erb
+++ b/app/views/tests/ticket_selector.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ticket_selector.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/app/views/tests/ui.html.erb b/app/views/tests/ui.html.erb
index 131824ae7..6d68e5d74 100644
--- a/app/views/tests/ui.html.erb
+++ b/app/views/tests/ui.html.erb
@@ -1,7 +1,6 @@
-
-
+<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ui.js", nonce: true %>
-
+<%= javascript_tag nonce: true do -%>
+<% end -%>
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index d3bcaa5ec..fab53696a 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -16,8 +16,29 @@
# # policy.report_uri "/csp-violation-report-endpoint"
# end
+Rails.application.config.content_security_policy do |policy|
+ base_uri = proc do
+ next if !Rails.env.production?
+ next if !Setting.get('system_init_done')
+
+ http_type = Setting.get('http_type')
+ fqdn = Setting.get('fqdn')
+
+ "#{http_type}://#{fqdn}"
+ end
+
+ policy.base_uri :self, base_uri
+
+ policy.default_src :self, :ws, :wss, 'https://log.zammad.com', 'https://images.zammad.com'
+ policy.font_src :self, :data
+ policy.img_src '*', :data
+ policy.object_src :none
+ policy.script_src :self, :unsafe_eval, :unsafe_inline, :strict_dynamic
+ policy.style_src :self, :unsafe_inline
+end
+
# If you are using UJS then enable automatic nonce generation
-# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
+Rails.application.config.content_security_policy_nonce_generator = ->(_request) { SecureRandom.base64(16) }
# Report CSP violations to a specified URI
# For further information see the following documentation: