diff --git a/app/styles/app.scss b/app/styles/app.scss
index 9d3ab9d98ad..85186a67ed6 100644
--- a/app/styles/app.scss
+++ b/app/styles/app.scss
@@ -342,3 +342,11 @@ h1 {
padding: 5px;
}
}
+
+.arrow-in-list svg {
+ background: #fff;
+}
+
+a.arrow svg {
+ background: #EEECDD;
+}
diff --git a/app/templates/components/category-list.hbs b/app/templates/components/category-list.hbs
index 155503f7045..172406d6ce4 100644
--- a/app/templates/components/category-list.hbs
+++ b/app/templates/components/category-list.hbs
@@ -3,7 +3,9 @@
{{#link-to 'category' category.slug class='name'}}
{{ category.category }} ({{ format-num category.crates_cnt }})
- {{svg-jar "right-arrow"}}
+
+ {{svg-jar "right-arrow"}}
+
{{/link-to}}
{{/each}}
diff --git a/app/templates/components/crate-list.hbs b/app/templates/components/crate-list.hbs
index 1663f04c4a9..dd0cebdd7fa 100644
--- a/app/templates/components/crate-list.hbs
+++ b/app/templates/components/crate-list.hbs
@@ -3,7 +3,9 @@
{{#link-to 'crate' crate.id class='name'}}
{{ crate.name }} ({{ crate.max_version }})
- {{svg-jar "right-arrow"}}
+
+ {{svg-jar "right-arrow"}}
+
{{/link-to}}
{{/each}}
diff --git a/app/templates/components/keyword-list.hbs b/app/templates/components/keyword-list.hbs
index 3f410e9e9b9..171350fb160 100644
--- a/app/templates/components/keyword-list.hbs
+++ b/app/templates/components/keyword-list.hbs
@@ -3,7 +3,9 @@
{{#link-to 'keyword' keyword class='name'}}
{{ keyword.id }} ({{ format-num keyword.crates_cnt }})
- {{svg-jar "right-arrow"}}
+
+ {{svg-jar "right-arrow"}}
+
{{/link-to}}
{{/each}}
diff --git a/app/templates/crate/version.hbs b/app/templates/crate/version.hbs
index 9cc4528b7f9..f3dcc984911 100644
--- a/app/templates/crate/version.hbs
+++ b/app/templates/crate/version.hbs
@@ -40,9 +40,6 @@
-{{! This is used to set the url of to actually download a file }}
-
-
{{#if currentVersion.yanked}}
diff --git a/app/templates/crate/versions.hbs b/app/templates/crate/versions.hbs
index 352246808b1..1873d57b651 100644
--- a/app/templates/crate/versions.hbs
+++ b/app/templates/crate/versions.hbs
@@ -22,7 +22,7 @@
{{/if}}
{{#link-to 'crate.version' version.num class='arrow'}}
- {{svg-jar "right-arrow" style="background-color: #EEECDD"}}
+ {{svg-jar "right-arrow"}}
{{/link-to}}
{{/each}}
diff --git a/public/assets/right-arrow.svg b/public/assets/right-arrow.svg
index 322066f086e..f44739eb1ff 100644
--- a/public/assets/right-arrow.svg
+++ b/public/assets/right-arrow.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/http.rs b/src/http.rs
index 9d8714ecddd..552bca78913 100644
--- a/src/http.rs
+++ b/src/http.rs
@@ -1,3 +1,5 @@
+use conduit::{Request, Response};
+use conduit_middleware::Middleware;
use curl;
use curl::easy::{Easy, List};
use oauth2::*;
@@ -6,7 +8,7 @@ use util::{CargoResult, internal, ChainError, human};
use serde_json;
use serde::Deserialize;
use std::str;
-
+use std::error::Error;
/// Does all the nonsense for sending a GET to Github. Doesn't handle parsing
/// because custom error-code handling may be desirable. Use
@@ -88,3 +90,48 @@ pub fn token(token: String) -> Token {
token_type: String::new(),
}
}
+
+#[derive(Clone, Copy, Debug)]
+pub struct SecurityHeadersMiddleware;
+
+impl Middleware for SecurityHeadersMiddleware {
+ fn after(
+ &self,
+ _: &mut Request,
+ mut res: Result>,
+ ) -> Result> {
+ if let Ok(ref mut response) = res {
+ // It would be better if we didn't have to have 'unsafe-eval' in the `script-src`
+ // policy, but google charts (used for the download graph on crate pages) uses `eval`
+ // to load scripts. Remove 'unsafe-eval' if google fixes the issue:
+ // https://github.com/google/google-visualization-issues/issues/1356
+ // or if we switch to a different graph generation library.
+ response.headers.insert(
+ "Content-Security-Policy".into(),
+ vec![
+ "default-src 'self'; \
+ connect-src 'self' https://docs.rs; \
+ script-src 'self' 'unsafe-eval' \
+ https://www.google-analytics.com https://www.google.com; \
+ style-src 'self' https://www.google.com https://ajax.googleapis.com; \
+ img-src *; \
+ object-src 'none'"
+ .into(),
+ ],
+ );
+ response.headers.insert(
+ "X-Content-Type-Options".into(),
+ vec!["nosniff".into()],
+ );
+ response.headers.insert(
+ "X-Frame-Options".into(),
+ vec!["SAMEORIGIN".into()],
+ );
+ response.headers.insert(
+ "X-XSS-Protection".into(),
+ vec!["1; mode=block".into()],
+ );
+ }
+ res
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index ff6ef9b471b..f9b462b0d76 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -227,6 +227,9 @@ pub fn middleware(app: Arc) -> MiddlewareBuilder {
cookie::Key::from_master(app.session_key.as_bytes()),
env == Env::Production,
));
+ if env == Env::Production {
+ m.add(http::SecurityHeadersMiddleware);
+ }
m.add(app::AppMiddleware::new(app));
// Run each request in a transaction and roll back the transaction if the request results