Merge branch 'next-minor' into develop

This commit is contained in:
Dennis Schubert 2016-09-30 02:11:36 +02:00
commit c41fd52f1d
No known key found for this signature in database
GPG key ID: 5A0304BEA7966D7E
14 changed files with 129 additions and 43 deletions

View file

@ -50,6 +50,7 @@ Note: Although this is a minor release, the configuration file changed because t
* Don't federate to pods that have been offline for an extended period of time [#7120](https://github.com/diaspora/diaspora/pull/7120)
* Add In-Reply-To and References headers to notification mails [#7122](https://github.com/diaspora/diaspora/pull/7122)
* Directly link to a comment in commented notification mails [#7124](https://github.com/diaspora/diaspora/pull/7124)
* Add optional `Content-Security-Policy` header [#7128](https://github.com/diaspora/diaspora/pull/7128)
# 0.6.0.1

View file

@ -137,6 +137,10 @@ gem "twitter-text", "1.14.0"
gem "ruby-oembed", "0.10.1"
gem "open_graph_reader", "0.6.1"
# Security Headers
gem "secure_headers", "3.4.1"
# Services
gem "omniauth", "1.3.1"
@ -211,10 +215,6 @@ group :production do # we don"t install these on travis to speed up test runs
gem "rack-google-analytics", "1.2.0"
gem "rack-piwik", "0.3.0", require: "rack/piwik"
# Click-jacking protection
gem "rack-protection", "1.5.3"
# Process management
gem "eye", "0.8.1"

View file

@ -780,6 +780,8 @@ GEM
scss_lint (0.49.0)
rake (>= 0.9, < 12)
sass (~> 3.4.20)
secure_headers (3.4.1)
useragent
securecompare (1.0.0)
shellany (0.0.1)
shoulda-matchers (3.1.1)
@ -877,6 +879,7 @@ GEM
get_process_mem (~> 0)
unicorn (>= 4, < 6)
url_safe_base64 (0.2.2)
useragent (0.16.8)
uuid (2.3.8)
macaddr (~> 1.0)
valid (1.2.0)
@ -993,7 +996,6 @@ DEPENDENCIES
rack-cors (= 0.4.0)
rack-google-analytics (= 1.2.0)
rack-piwik (= 0.3.0)
rack-protection (= 1.5.3)
rack-rewrite (= 1.5.1)
rack-ssl (= 1.4.1)
rails (= 4.2.7.1)
@ -1026,6 +1028,7 @@ DEPENDENCIES
ruby-oembed (= 0.10.1)
rubyzip (= 1.2.0)
sass-rails (= 5.0.6)
secure_headers (= 3.4.1)
shoulda-matchers (= 3.1.1)
sidekiq (= 4.1.4)
sidekiq-cron (= 0.4.2)

View file

@ -5,7 +5,7 @@
module AnalyticsHelper
def include_mixpanel
include_analytics "mixpanel" do
javascript_tag do
nonced_javascript_tag do
<<-JS.html_safe
(function(d,c){var a,b,g,e;a=d.createElement('script');a.type='text/javascript';a.async=!0;a.src=('https:'===d.location.protocol?'https:':'http:')+'//api.mixpanel.com/site_media/js/api/mixpanel.2.js';b=d.getElementsByTagName('script')[0];b.parentNode.insertBefore(a,b);c._i=[];c.init=function(a,d,f){var b=c;'undefined'!==typeof f?b=c[f]=[]:f='mixpanel';g='disable track track_pageview track_links track_forms register register_once unregister identify name_tag set_config'.split(' ');
for(e=0;e<g.length;e++)(function(a){b[a]=function(){b.push([a].concat(Array.prototype.slice.call(arguments,0)))}})(g[e]);c._i.push([a,d,f])};window.mixpanel=c})(document,[]);
@ -18,7 +18,7 @@ module AnalyticsHelper
def include_mixpanel_guid
return unless current_user
include_analytics "mixpanel" do
javascript_tag do
nonced_javascript_tag do
<<-JS.html_safe
mixpanel.name_tag("#{current_user.guid}");
JS
@ -28,12 +28,12 @@ module AnalyticsHelper
def chartbeat_head_block
return unless configured?("chartbeat")
javascript_tag("var _sf_startpt=(new Date()).getTime()")
nonced_javascript_tag("var _sf_startpt=(new Date()).getTime()")
end
def include_chartbeat
include_analytics "chartbeat" do
javascript_tag do
nonced_javascript_tag do
<<-JS.html_safe
var _sf_async_config = { uid: #{AppConfig.privacy.chartbeat_uid}, domain: "#{AppConfig.pod_uri.host}" };
(function() {

View file

@ -53,14 +53,14 @@ module ApplicationHelper
buf = []
if AppConfig.privacy.jquery_cdn?
version = Jquery::Rails::JQUERY_2_VERSION
buf << [ javascript_include_tag("//code.jquery.com/jquery-#{version}.min.js") ]
buf << [javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery2')}'));")]
buf << [javascript_include_tag("//code.jquery.com/jquery-#{version}.min.js")]
buf << [nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery2')}'));")]
else
buf << [javascript_include_tag("jquery2")]
end
buf << [ javascript_include_tag('jquery_ujs') ]
buf << [ javascript_tag("jQuery.ajaxSetup({'cache': false});") ]
buf << [ javascript_tag("$.fx.off = true;") ] if Rails.env.test?
buf << [javascript_include_tag("jquery_ujs")]
buf << [nonced_javascript_tag("jQuery.ajaxSetup({'cache': false});")]
buf << [nonced_javascript_tag("$.fx.off = true;")] if Rails.env.test?
buf.join("\n").html_safe
end
end

View file

@ -20,7 +20,7 @@ module LayoutHelper
end
def load_javascript_locales(section = 'javascripts')
content_tag(:script) do
nonced_javascript_tag do
<<-JS.html_safe
Diaspora.I18n.load(#{get_javascript_strings_for(I18n.locale, section).to_json},
"#{I18n.locale}",
@ -51,7 +51,7 @@ module LayoutHelper
end
def old_browser_js_support
content_tag(:script) do
nonced_javascript_tag do
<<-JS.html_safe
if(Array.isArray === undefined) {
Array.isArray = function (arg) {

View file

@ -2,25 +2,26 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
:javascript
$(document).ready(function () {
var data = $.parseJSON( "#{escape_javascript(@contacts_json)}" ),
autocompleteInput = $("#contact-autocomplete");
%script{nonce: content_security_policy_nonce(:script)}
:plain
$(document).ready(function () {
var data = $.parseJSON( "#{escape_javascript(@contacts_json).html_safe}" ),
autocompleteInput = $("#contact-autocomplete");
autocompleteInput.autoSuggest(data, {
selectedItemProp: "name",
searchObjProps: "name",
asHtmlID: "contact_ids",
retrieveLimit: 10,
minChars: 1,
keyDelay: 0,
startText: '',
emptyText: "#{t('no_results')}",
preFill: [{name : "#{h params[:name]}",
value : "#{@contact_ids}"}]
});
autocompleteInput.focus();
});
autocompleteInput.autoSuggest(data, {
selectedItemProp: "name",
searchObjProps: "name",
asHtmlID: "contact_ids",
retrieveLimit: 10,
minChars: 1,
keyDelay: 0,
startText: '',
emptyText: "#{t("no_results")}",
preFill: [{name : "#{h params[:name]}",
value : "#{@contact_ids}"}]
});
autocompleteInput.focus();
});
.col-md-6#new_conversation_pane
.container-fluid.row

View file

@ -41,7 +41,7 @@
= csrf_meta_tag
= include_gon(camel_case: true)
= include_gon(camel_case: true, nonce: content_security_policy_nonce(:script))
%body{ class: "page-#{controller_name} action-#{action_name}" }
= yield :before_content

View file

@ -52,7 +52,7 @@
= yield(:head)
= include_gon(:camel_case => true)
= include_gon(camel_case: true, nonce: content_security_policy_nonce(:script))
%body
#app
= render "layouts/header"

View file

@ -17,6 +17,5 @@ if defined?(Unicorn)
end
use Rack::Deflater
use Rack::InternetExplorerVersion, minimum: 9
use Rack::Protection::FrameOptions
run Diaspora::Application

View file

@ -148,6 +148,9 @@ defaults:
default_metas:
title: 'diaspora* social network'
description: 'diaspora* is the online social world where you are in control.'
csp:
report_only: true
report_uri:
services:
facebook:
enable: false

View file

@ -551,6 +551,26 @@ configuration: ## Section
#title: 'diaspora* social network'
#description: 'diaspora* is the online social world where you are in control.'
## CSP (Content Security Policy) header
## CSP allows limiting origins from where resources are allowed to be loaded. This
## improves security, since it helps to detect and mitigate cross-site scripting
## and data injection attacks. The default policy of diaspora* allows all third
## party domains from services that are included in diaspora*, like OEmbed
## scripts, so you can safely activate it by setting `report_only` to false. If
## you customized diaspora* (edited templates or added own JS), additional work
## may be required. You can test the policy with the "report_uri". Our default CSP
## does not work with Google analytics or Piwik, because they inject JS code that
## is blocked by CSP.
csp:
## Report-Only header (default=true)
## By default diaspora* adds only a "Content-Security-Policy-Report-Only" header. If you set
## this to false, the "Content-Security-Policy" header is added instead.
#report_only: false
## CSP report URI (default=)
## You can set an URI here, where the user agent reports violations as JSON document via a POST request.
#report_uri: "/csp_violation_reports"
## Posting from Diaspora to external services (all are disabled by default).
services: ## Section

View file

@ -0,0 +1,59 @@
SecureHeaders::Configuration.default do |config|
config.hsts = SecureHeaders::OPT_OUT # added by Rack::SSL
config.csp = {
default_src: %w('none'),
child_src: %w('self' www.youtube.com w.soundcloud.com twitter.com platform.twitter.com syndication.twitter.com
player.vimeo.com www.mixcloud.com www.dailymotion.com media.ccc.de bandcamp.com
www.instagram.com),
connect_src: %w('self' embedr.flickr.com geo.query.yahoo.com nominatim.openstreetmap.org api.github.com),
font_src: %w('self'),
form_action: %w('self' platform.twitter.com syndication.twitter.com),
frame_ancestors: %w('self'),
img_src: %w('self' data: *),
media_src: %w(https:),
script_src: %w('self' 'unsafe-eval' platform.twitter.com cdn.syndication.twimg.com widgets.flickr.com
embedr.flickr.com platform.instagram.com 'unsafe-inline'),
style_src: %w('self' 'unsafe-inline' platform.twitter.com *.twimg.com)
}
if AppConfig.environment.assets.host.present?
asset_host = Addressable::URI.parse(AppConfig.environment.assets.host.get).host
config.csp[:script_src] << asset_host
config.csp[:style_src] << asset_host
end
if AppConfig.chat.enabled?
config.csp[:media_src] << "data:"
unless AppConfig.chat.server.bosh.proxy?
config.csp[:connect_src] << "#{AppConfig.pod_uri.host}:#{AppConfig.chat.server.bosh.port}"
end
end
if AppConfig.privacy.mixpanel_uid.present?
config.csp[:script_src] << "api.mixpanel.com"
config.csp[:connect_src] << "api.mixpanel.com"
end
config.csp[:script_src] << "code.jquery.com" if AppConfig.privacy.jquery_cdn?
config.csp[:script_src] << "static.chartbeat.com" if AppConfig.privacy.chartbeat_uid.present?
config.csp[:form_action] << "www.paypal.com" if AppConfig.settings.paypal_donations.enable?
config.csp[:report_only] = AppConfig.settings.csp.report_only?
config.csp[:report_uri] = [AppConfig.settings.csp.report_uri] if AppConfig.settings.csp.report_uri.present?
# Add frame-src but don't spam the log with DEPRECATION warnings.
# We need frame-src to support older versions of Chrome, because secure_headers handles all Chrome browsers as
# "modern" browser, and ignores the version of the browser. We can drop this once we support only Chrome
# versions with child-src support.
module SecureHeaders
class ContentSecurityPolicy
private
def normalize_child_frame_src
@config[:frame_src] = @config[:child_src]
end
end
end
end

View file

@ -60,11 +60,11 @@ describe ApplicationHelper, :type => :helper do
end
it 'inclues jquery.js from jquery cdn' do
expect(jquery_include_tag).to match(/jquery\.com/)
expect(helper.jquery_include_tag).to match(/jquery\.com/)
end
it 'falls back to asset pipeline on cdn failure' do
expect(jquery_include_tag).to match(/document\.write/)
expect(helper.jquery_include_tag).to match(/document\.write/)
end
end
@ -74,17 +74,17 @@ describe ApplicationHelper, :type => :helper do
end
it 'includes jquery.js from asset pipeline' do
expect(jquery_include_tag).to match(/jquery2\.js/)
expect(jquery_include_tag).not_to match(/jquery\.com/)
expect(helper.jquery_include_tag).to match(/jquery2\.js/)
expect(helper.jquery_include_tag).not_to match(/jquery\.com/)
end
end
it 'inclues jquery_ujs.js' do
expect(jquery_include_tag).to match(/jquery_ujs\.js/)
expect(helper.jquery_include_tag).to match(/jquery_ujs\.js/)
end
it "disables ajax caching" do
expect(jquery_include_tag).to match(/jQuery\.ajaxSetup/)
expect(helper.jquery_include_tag).to match(/jQuery\.ajaxSetup/)
end
end