Maintenance: Add Content Security Policy.

This commit is contained in:
Thorsten Eckel 2020-02-13 09:35:58 +01:00
parent 33498bac91
commit 49b0ca4d58
38 changed files with 184 additions and 129 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -247,7 +247,7 @@ class _i18nSingleton extends Spine.Module
return string if !string
if App.Config.get('translation_inline')
return '<span class="translation" onkeydown="arguments[0].stopPropagation(); return true" onclick="arguments[0].stopPropagation(); return false" contenteditable="true" title="' + App.Utils.htmlEscape(string) + '">' + App.Utils.htmlEscape(@translate(string)) + '</span>'
return '<span class="translation" contenteditable="true" title="' + App.Utils.htmlEscape(string) + '">' + App.Utils.htmlEscape(@translate(string)) + '</span>'
translated = @translate(string, args, true, true)

View file

@ -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) ->

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
<!-- svgstore fallback -->
<script>
<%= javascript_tag nonce: true do -%>
/*
detect if browser is
- Chrome 14-20
@ -27,7 +27,7 @@
xhr.open('get', 'assets/images/icons.svg', true)
xhr.send()
})(document)
</script>
<% end -%>
<div id="app"></div>
<div class="splash">
<svg class="icon icon-logo"><use xlink:href="assets/images/icons.svg#icon-logo" /></svg>

View file

@ -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 %>
</head>

View file

@ -70,10 +70,13 @@
</footer>
</div>
<script type='text/javascript'>
<%= javascript_tag nonce: true do -%>
if(window.fetch === undefined || window.Promise === undefined || Element.prototype.prepend === undefined){
document.write('<script src="<%= path_to_javascript('knowledge_base_public_polyfills') %>"><\/script>')
var polyfillScriptTag = document.createElement('script');
polyfillScriptTag.setAttribute('src', '<%= path_to_javascript('knowledge_base_public_polyfills') %>');
polyfillScriptTag.setAttribute('nonce', '<%= content_security_policy_nonce %>');
document.body.appendChild(polyfillScriptTag);
}
</script>
<% end -%>
<%= javascript_include_tag 'knowledge_base_public' %>
<%= javascript_include_tag 'knowledge_base_public', nonce: true %>

View file

@ -1,7 +1,5 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/color_object.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/color_object.js", nonce: true %>
<style type="text/css">
body {
@ -9,7 +7,7 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,5 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/core.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/core.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +7,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,8 +1,5 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/syn-0.14.1.js"></script>
<script src="/assets/tests/form_color.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/syn-0.14.1.js", "/assets/tests/form_color.js", nonce: true %>
<style type="text/css">
body {
@ -10,8 +7,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_column_select.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_column_select.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_extended.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_extended.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_find.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_find.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_searchable_select.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_searchable_select.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_ticket_perform_action.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_ticket_perform_action.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_timer.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_timer.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_tree_select.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_tree_select.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_trim.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_trim.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/form_validation.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/form_validation.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/html_utils.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/html_utils.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,6 +1,5 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/i18n.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/i18n.js", nonce: true %>
<style type="text/css">
body {
@ -8,7 +7,7 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/local_storage.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/local_storage.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/model.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/model_binding.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_binding.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/model_ticket.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_ticket.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/model_ui.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/model_ui.js", nonce: true %>
<style type="text/css">
body {
@ -9,7 +8,7 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/session.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/session.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/table.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/table.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/table_extended.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/table_extended.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/taskbar.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/taskbar.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/text_module.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/text_module.js", nonce: true %>
<style type="text/css">
body {
@ -9,8 +8,8 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/ticket_selector.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ticket_selector.js", nonce: true %>
<style type="text/css">
body {
@ -9,7 +8,7 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -1,7 +1,6 @@
<link rel="stylesheet" href="/assets/tests/qunit-1.21.0.css">
<script src="/assets/tests/qunit-1.21.0.js"></script>
<script src="/assets/tests/ui.js"></script>
<%= javascript_include_tag "/assets/tests/qunit-1.21.0.js", "/assets/tests/ui.js", nonce: true %>
<style type="text/css">
body {
@ -9,7 +8,7 @@ body {
}
</style>
<script type="text/javascript">
</script>
<%= javascript_tag nonce: true do -%>
<% end -%>
<div id="qunit" class="u-dontfold"></div>

View file

@ -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: