aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrhenium <rhenium@rhe.jp>2014-10-06 08:53:22 +0900
committerrhenium <rhenium@rhe.jp>2014-10-06 08:53:22 +0900
commit5d32ae79c63074de3ab11296e4ebbe7d42f37d3b (patch)
treed697c5868f0e28efa1360da05782f5b1ef884a26
parent3d1a4777e35618ae56a5e1e4d0d48451ed71c6d7 (diff)
downloadaclog-5d32ae79c63074de3ab11296e4ebbe7d42f37d3b.tar.gz
web: introduce Content Security Policy (CSP)
-rw-r--r--app/assets/javascripts/layouts.js.erb15
-rw-r--r--app/assets/javascripts/tweets.js.erb (renamed from app/assets/javascripts/tweets.js)3
-rw-r--r--app/controllers/application_controller.rb1
-rw-r--r--app/controllers/concerns/security_headers.rb19
-rw-r--r--app/helpers/application_helper.rb3
-rw-r--r--app/views/layouts/_base.html.haml1
-rw-r--r--app/views/tweets/_tweet_stats.html.haml4
7 files changed, 37 insertions, 9 deletions
diff --git a/app/assets/javascripts/layouts.js.erb b/app/assets/javascripts/layouts.js.erb
index fd9b044..f7943dd 100644
--- a/app/assets/javascripts/layouts.js.erb
+++ b/app/assets/javascripts/layouts.js.erb
@@ -11,12 +11,15 @@ $(function() {
if (previousText.length > 0) {
$.getJSON("/i/user_jump_suggest.json", { head: previousText }, function(json) {
+ var menu = $("#user-jump-dropdown .dropdown-menu");
json.forEach(function(s) {
- $("#user-jump-dropdown .dropdown-menu")
- .append($("<li />").addClass("user-jump-suggestion")
- .append($("<a />").attr("href", "/" + s.screen_name).attr("title", s.name + " (@" + s.screen_name + ")")
- .append($("<img />").addClass("twitter-icon").attr("src", s.profile_image_url).attr("alt", "@" + s.screen_name).attr("onerror", "this.src = '<%= image_path("profile_image_missing.png") %>'"))
- .append($("<span />").text("@" + s.screen_name))));
+ var img = $("<img />").addClass("twitter-icon").attr("src", s.profile_image_url).attr("alt", "@" + s.screen_name);
+ img.on("error", function() { this.src = '<%= image_path("profile_image_missing.png") %>'; });
+
+ menu.append($("<li />").addClass("user-jump-suggestion")
+ .append($("<a />").attr("href", "/" + s.screen_name).attr("title", s.name + " (@" + s.screen_name + ")")
+ .append(img)
+ .append($("<span />").text("@" + s.screen_name))));
});
});
}
@@ -26,4 +29,6 @@ $(function() {
window.location = "/" + $("input", this).val();
return false;
});
+
+ $("img.twitter-icon").on("error", function() { this.src = '<%= image_path("profile_image_missing.png") %>'; });
});
diff --git a/app/assets/javascripts/tweets.js b/app/assets/javascripts/tweets.js.erb
index 25fa145..659c76b 100644
--- a/app/assets/javascripts/tweets.js
+++ b/app/assets/javascripts/tweets.js.erb
@@ -5,6 +5,9 @@ Application.tweets = {
$(this).text(new Date($(this).attr("datetime"))
.toLocaleString());
});
+ $("img.twitter-icon", d).each(function() {
+ $(this).on("error", function() { this.src = '<%= image_path("profile_image_missing.png") %>'; });
+ });
};
formatTweet($(".statuses"));
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index db1edd8..0052b01 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,4 +1,5 @@
class ApplicationController < ActionController::Base
+ include SecurityHeaders
include ControllerErrorHandling if Rails.env.production?
protect_from_forgery with: :exception
diff --git a/app/controllers/concerns/security_headers.rb b/app/controllers/concerns/security_headers.rb
new file mode 100644
index 0000000..e2d3d85
--- /dev/null
+++ b/app/controllers/concerns/security_headers.rb
@@ -0,0 +1,19 @@
+module SecurityHeaders
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :set_csp_header
+ end
+
+ def set_csp_header
+ policy = {
+ "default-src" => "'self'",
+ "img-src" => "'self' https://pbs.twimg.com https://abs.twimg.com",
+ "style-src" => "'self' http://fonts.googleapis.com",
+ "font-src" => "'self' http://fonts.gstatic.com",
+ "frame-src" => "'self' http://platform.twitter.com"
+ }
+ policy_str = policy.map {|k, v| "#{k} #{v}" }.join("; ")
+ response["Content-Security-Policy"] = policy_str
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 5fe6350..ede2c51 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -19,8 +19,7 @@ module ApplicationHelper
capture_haml do
haml_tag("img.twitter-icon",
{ src: user.profile_image_url(size),
- alt: "@" + user.screen_name,
- onerror: "this.src = '#{image_path("profile_image_missing.png")}'"
+ alt: "@" + user.screen_name
}.merge(options))
end
end
diff --git a/app/views/layouts/_base.html.haml b/app/views/layouts/_base.html.haml
index 3282123..c6066f2 100644
--- a/app/views/layouts/_base.html.haml
+++ b/app/views/layouts/_base.html.haml
@@ -7,6 +7,7 @@
%link{rel: "apple-touch-icon-precomposed", href: image_path("apple-touch-icon-precomposed.png")}
%meta{name: "msapplication-TileImage", content: image_path("tile-image.png")}
%meta{name: "msapplication-TileColor", content: "#f0eadb"}
+ %meta{name: "twitter:widgets:csp", content: "on"}
= stylesheet_link_tag "application", media: nil, "data-turbolinks-track" => true
= javascript_include_tag "application", "data-turbolinks-track" => true
= csrf_meta_tags
diff --git a/app/views/tweets/_tweet_stats.html.haml b/app/views/tweets/_tweet_stats.html.haml
index 517ba9a..5c0919d 100644
--- a/app/views/tweets/_tweet_stats.html.haml
+++ b/app/views/tweets/_tweet_stats.html.haml
@@ -2,7 +2,7 @@
- if tweet.favorites_count > 0
%dl
%dt
- %a.expand-responses-button{href: "javascript:void(0)", title: "すべて見る", data: { type: "favorites", id: tweet.id }}<
+ %a.expand-responses-button{href: "#", title: "すべて見る", data: { type: "favorites", id: tweet.id }}<
%span>= tweet.favorites_count
Favs
%dd
@@ -11,7 +11,7 @@
- if tweet.retweets_count > 0
%dl
%dt
- %a.expand-responses-button{href: "javascript:void(0)", title: "すべて見る", data: { type: "retweets", id: tweet.id }}<
+ %a.expand-responses-button{href: "#", title: "すべて見る", data: { type: "retweets", id: tweet.id }}<
%span>= tweet.retweets_count
RTs
%dd