From f516e317ea639bf0d2cdf3d1f1e2e00b5b7c90ef Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:10:21 +0000 Subject: [PATCH 01/12] plugs: add CSPPlug --- lib/pleroma/plugs/csp_plug.ex | 38 +++++++++++++++++++++++++++++++++++ lib/pleroma/web/endpoint.ex | 1 + 2 files changed, 39 insertions(+) create mode 100644 lib/pleroma/plugs/csp_plug.ex diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex new file mode 100644 index 000000000..15d466c36 --- /dev/null +++ b/lib/pleroma/plugs/csp_plug.ex @@ -0,0 +1,38 @@ +defmodule Pleroma.Plugs.CSPPlug do + import Plug.Conn + + def init(opts), do: opts + + def call(conn, options) do + conn = merge_resp_headers(conn, headers()) + end + + defp headers do + [ + {"x-xss-protection", "1; mode=block"}, + {"x-permitted-cross-domain-policies", "none"}, + {"x-frame-options", "DENY"}, + {"x-content-type-options", "nosniff"}, + {"referrer-policy", "same-origin"}, + {"x-download-options", "noopen"}, + {"content-security-policy", csp_string() <> ";"} + ] + end + + defp csp_string do + [ + "default-src 'none'", + "base-uri 'self'", + "form-action *", + "frame-ancestors 'none'", + "img-src 'self' data: https:", + "media-src 'self' https:", + "style-src 'self' 'unsafe-inline'", + "font-src 'self'", + "script-src 'self'", + "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"), + "upgrade-insecure-requests" + ] + |> Enum.join("; ") + end +end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index cb5de087b..370d2d792 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -12,6 +12,7 @@ defmodule Pleroma.Web.Endpoint do # You should set gzip to true if you are running phoenix.digest # when deploying your static files in production. plug(CORSPlug) + plug(Pleroma.Plugs.CSPPlug) plug(Plug.Static, at: "/media", from: Pleroma.Uploaders.Local.upload_path(), gzip: false) From 057a9017b3852f10e76165b70b907d9af458c301 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:12:26 +0000 Subject: [PATCH 02/12] example configs: remove obsolete CSP configuration --- installation/caddyfile-pleroma.example | 17 ----------------- installation/pleroma-apache.conf | 6 ------ installation/pleroma.nginx | 8 -------- installation/pleroma.vcl | 5 ----- 4 files changed, 36 deletions(-) diff --git a/installation/caddyfile-pleroma.example b/installation/caddyfile-pleroma.example index 305f2aa79..c34b47045 100644 --- a/installation/caddyfile-pleroma.example +++ b/installation/caddyfile-pleroma.example @@ -22,27 +22,10 @@ example.tld { } header / { - X-XSS-Protection "1; mode=block" - X-Frame-Options "DENY" - X-Content-Type-Options "nosniff" - Referrer-Policy "same-origin" Strict-Transport-Security "max-age=31536000; includeSubDomains;" Expect-CT "enforce, max-age=2592000" - Content-Security-Policy "default-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://{host}; upgrade-insecure-requests;" } - # If you do not want remote frontends to be able to access your Pleroma backend server, remove these lines. - # If you want to allow all origins access, remove the origin lines. - # To use this directive, you need the http.cors plugin for Caddy. - cors / { - origin https://halcyon.example.tld - origin https://pinafore.example.tld - methods POST,PUT,DELETE,GET,PATCH,OPTIONS - allowed_headers Authorization,Content-Type,Idempotency-Key - exposed_headers Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id - } - # Stop removing lines here. - # If you do not want to use the mediaproxy function, remove these lines. # To use this directive, you need the http.cache plugin for Caddy. cache { diff --git a/installation/pleroma-apache.conf b/installation/pleroma-apache.conf index fb777983e..cbb165064 100644 --- a/installation/pleroma-apache.conf +++ b/installation/pleroma-apache.conf @@ -34,12 +34,6 @@ CustomLog ${APACHE_LOG_DIR}/access.log combined SSLCompression off SSLSessionTickets off - Header always set X-Xss-Protection "1; mode=block" - Header always set X-Frame-Options "DENY" - Header always set X-Content-Type-Options "nosniff" - Header always set Referrer-Policy same-origin - Header always set Content-Security-Policy "default-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://${servername}; upgrade-insecure-requests;" - # Uncomment this only after you get HTTPS working. # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 9b7419497..62c99383f 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -60,14 +60,6 @@ server { client_max_body_size 16m; location / { - add_header X-XSS-Protection "1; mode=block" always; - add_header X-Permitted-Cross-Domain-Policies "none" always; - add_header X-Frame-Options "DENY" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "same-origin" always; - add_header X-Download-Options "noopen" always; - add_header Content-Security-Policy "default-src 'none'; base-uri 'self'; form-action *; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://$server_name; upgrade-insecure-requests;" always; - # Uncomment this only after you get HTTPS working. # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; diff --git a/installation/pleroma.vcl b/installation/pleroma.vcl index 74490be2a..5d80c6f44 100644 --- a/installation/pleroma.vcl +++ b/installation/pleroma.vcl @@ -121,11 +121,6 @@ sub vcl_pipe { } sub vcl_deliver { - set resp.http.X-Frame-Options = "DENY"; - set resp.http.X-XSS-Protection = "1; mode=block"; - set resp.http.X-Content-Type-Options = "nosniff"; - set resp.http.Referrer-Policy = "same-origin"; - set resp.http.Content-Security-Policy = "default-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://" + req.http.host + "; upgrade-insecure-requests;"; # Uncomment this only after you get HTTPS working. # set resp.http.Strict-Transport-Security= "max-age=31536000; includeSubDomains"; } From 69f5dfcfb3f2b498e1f9957244f0896b6f9d5c2a Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:37:18 +0000 Subject: [PATCH 03/12] config: add default parameters for CSPPlug --- config/config.exs | 5 +++++ config/config.md | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/config/config.exs b/config/config.exs index e82c490e3..ad8653025 100644 --- a/config/config.exs +++ b/config/config.exs @@ -176,6 +176,11 @@ limit: 23, web: "https://vinayaka.distsn.org/?{{host}}+{{user}}" +config :pleroma, :csp, + enabled: true, + sts: false, + sts_max_age: 31_536_000 + config :cors_plug, max_age: 86_400, methods: ["POST", "PUT", "DELETE", "GET", "PATCH", "OPTIONS"], diff --git a/config/config.md b/config/config.md index 51172fc4d..e08d206b6 100644 --- a/config/config.md +++ b/config/config.md @@ -80,3 +80,8 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i * ``unfollow_blocked``: Whether blocks result in people getting unfollowed * ``outgoing_blocks``: Whether to federate blocks to other instances * ``deny_follow_blocked``: Whether to disallow following an account that has blocked the user in question + +## :csp +* ``enabled``: Whether the managed content security policy is enabled +* ``sts``: Whether to additionally send a `Strict-Transport-Security` header +* ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent From a2bf5426cb84940dbd58aec10a7b1b0a90f26a60 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:42:14 +0000 Subject: [PATCH 04/12] sample config: document how to make CSPPlug send STS headers (off by default to allow for SSL debugging) --- lib/mix/tasks/sample_config.eex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index 3881ead26..824bc97a1 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -25,6 +25,10 @@ config :pleroma, Pleroma.Repo, hostname: "localhost", pool_size: 10 +# Enable Strict-Transport-Security once SSL is working: +# config :pleroma, :csp, +# sts: true + # Configure S3 support if desired. # The public S3 endpoint is different depending on region and provider, # consult your S3 provider's documentation for details on what to use. From 331cf6ada1e4df51b366c79126e094ee335dd684 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:50:28 +0000 Subject: [PATCH 05/12] csp plug: add sts support --- lib/pleroma/plugs/csp_plug.ex | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex index 15d466c36..56f2376ee 100644 --- a/lib/pleroma/plugs/csp_plug.ex +++ b/lib/pleroma/plugs/csp_plug.ex @@ -1,10 +1,17 @@ defmodule Pleroma.Plugs.CSPPlug do + alias Pleroma.Config import Plug.Conn def init(opts), do: opts def call(conn, options) do - conn = merge_resp_headers(conn, headers()) + if Config.get([:csp, :enabled]) do + conn = + merge_resp_headers(conn, headers()) + |> maybe_send_sts_header(Config.get([:csp, :sts])) + else + conn + end end defp headers do @@ -35,4 +42,14 @@ defp csp_string do ] |> Enum.join("; ") end + + defp maybe_send_sts_header(conn, true) do + max_age = Config.get([:csp, :sts_max_age]) + + merge_resp_headers(conn, [ + {"strict-transport-security", "max-age=#{max_age}; includeSubDomains"} + ]) + end + + defp maybe_send_sts_header(conn, _), do: conn end From df72978dce3805157537e8fa1a2fec35fcf9a7cd Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:53:42 +0000 Subject: [PATCH 06/12] csp plug: add support for certificate transparency --- config/config.exs | 3 ++- config/config.md | 1 + lib/pleroma/plugs/csp_plug.ex | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/config/config.exs b/config/config.exs index ad8653025..1d918919d 100644 --- a/config/config.exs +++ b/config/config.exs @@ -179,7 +179,8 @@ config :pleroma, :csp, enabled: true, sts: false, - sts_max_age: 31_536_000 + sts_max_age: 31_536_000, + ct_max_age: 2_592_000 config :cors_plug, max_age: 86_400, diff --git a/config/config.md b/config/config.md index e08d206b6..34f703560 100644 --- a/config/config.md +++ b/config/config.md @@ -85,3 +85,4 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i * ``enabled``: Whether the managed content security policy is enabled * ``sts``: Whether to additionally send a `Strict-Transport-Security` header * ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent +* ``ct_max_age``: The maximum age for the `Except-CT` header if sent diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex index 56f2376ee..8fc21b909 100644 --- a/lib/pleroma/plugs/csp_plug.ex +++ b/lib/pleroma/plugs/csp_plug.ex @@ -44,10 +44,12 @@ defp csp_string do end defp maybe_send_sts_header(conn, true) do - max_age = Config.get([:csp, :sts_max_age]) + max_age_sts = Config.get([:csp, :sts_max_age]) + max_age_ct = Config.get([:csp, :ct_max_age]) merge_resp_headers(conn, [ - {"strict-transport-security", "max-age=#{max_age}; includeSubDomains"} + {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, + {"expect-ct", "enforce, max-age=#{max_age_ct}"} ]) end From e4bd5a6950d08eddbbc12ddd3f2e91c43544238c Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:56:46 +0000 Subject: [PATCH 07/12] example configs: kill STS/CT headers --- installation/caddyfile-pleroma.example | 5 ----- installation/pleroma-apache.conf | 3 --- installation/pleroma.nginx | 3 --- installation/pleroma.vcl | 5 ----- 4 files changed, 16 deletions(-) diff --git a/installation/caddyfile-pleroma.example b/installation/caddyfile-pleroma.example index c34b47045..03ff000b6 100644 --- a/installation/caddyfile-pleroma.example +++ b/installation/caddyfile-pleroma.example @@ -21,11 +21,6 @@ example.tld { ciphers ECDHE-ECDSA-WITH-CHACHA20-POLY1305 ECDHE-RSA-WITH-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 } - header / { - Strict-Transport-Security "max-age=31536000; includeSubDomains;" - Expect-CT "enforce, max-age=2592000" - } - # If you do not want to use the mediaproxy function, remove these lines. # To use this directive, you need the http.cache plugin for Caddy. cache { diff --git a/installation/pleroma-apache.conf b/installation/pleroma-apache.conf index cbb165064..d5e75044f 100644 --- a/installation/pleroma-apache.conf +++ b/installation/pleroma-apache.conf @@ -34,9 +34,6 @@ CustomLog ${APACHE_LOG_DIR}/access.log combined SSLCompression off SSLSessionTickets off - # Uncomment this only after you get HTTPS working. - # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" - RewriteEngine On RewriteCond %{HTTP:Connection} Upgrade [NC] RewriteCond %{HTTP:Upgrade} websocket [NC] diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 62c99383f..f0e684f2c 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -60,9 +60,6 @@ server { client_max_body_size 16m; location / { - # Uncomment this only after you get HTTPS working. - # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; diff --git a/installation/pleroma.vcl b/installation/pleroma.vcl index 5d80c6f44..63c1cb74d 100644 --- a/installation/pleroma.vcl +++ b/installation/pleroma.vcl @@ -119,8 +119,3 @@ sub vcl_pipe { set bereq.http.connection = req.http.connection; } } - -sub vcl_deliver { - # Uncomment this only after you get HTTPS working. - # set resp.http.Strict-Transport-Security= "max-age=31536000; includeSubDomains"; -} From 54fdce9107af85321d3ce73ec59a48567dc1bdba Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 07:26:31 +0000 Subject: [PATCH 08/12] tests: add tests for CSPPlug --- test/plugs/csp_plug_test.exs | 61 ++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/plugs/csp_plug_test.exs diff --git a/test/plugs/csp_plug_test.exs b/test/plugs/csp_plug_test.exs new file mode 100644 index 000000000..e27b24db9 --- /dev/null +++ b/test/plugs/csp_plug_test.exs @@ -0,0 +1,61 @@ +defmodule Pleroma.Web.Plugs.CSPPlugTest do + use Pleroma.Web.ConnCase + alias Pleroma.Config + alias Plug.Conn + + test "it sends CSP headers when enabled", %{conn: conn} do + Config.put([:csp, :enabled], true) + + conn = + conn + |> get("/api/v1/instance") + + refute Conn.get_resp_header(conn, "x-xss-protection") == [] + refute Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == [] + refute Conn.get_resp_header(conn, "x-frame-options") == [] + refute Conn.get_resp_header(conn, "x-content-type-options") == [] + refute Conn.get_resp_header(conn, "x-download-options") == [] + refute Conn.get_resp_header(conn, "referrer-policy") == [] + refute Conn.get_resp_header(conn, "content-security-policy") == [] + end + + test "it does not send CSP headers when disabled", %{conn: conn} do + Config.put([:csp, :enabled], false) + + conn = + conn + |> get("/api/v1/instance") + + assert Conn.get_resp_header(conn, "x-xss-protection") == [] + assert Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == [] + assert Conn.get_resp_header(conn, "x-frame-options") == [] + assert Conn.get_resp_header(conn, "x-content-type-options") == [] + assert Conn.get_resp_header(conn, "x-download-options") == [] + assert Conn.get_resp_header(conn, "referrer-policy") == [] + assert Conn.get_resp_header(conn, "content-security-policy") == [] + end + + test "it sends STS headers when enabled", %{conn: conn} do + Config.put([:csp, :enabled], true) + Config.put([:csp, :sts], true) + + conn = + conn + |> get("/api/v1/instance") + + refute Conn.get_resp_header(conn, "strict-transport-security") == [] + refute Conn.get_resp_header(conn, "expect-ct") == [] + end + + test "it does not send STS headers when disabled", %{conn: conn} do + Config.put([:csp, :enabled], true) + Config.put([:csp, :sts], false) + + conn = + conn + |> get("/api/v1/instance") + + assert Conn.get_resp_header(conn, "strict-transport-security") == [] + assert Conn.get_resp_header(conn, "expect-ct") == [] + end +end From 5dda13ee5f9302cfef215c8ffaa527e9a572a37b Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 07:27:36 +0000 Subject: [PATCH 09/12] config docs: typo fix --- config/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.md b/config/config.md index 34f703560..446b0ce67 100644 --- a/config/config.md +++ b/config/config.md @@ -85,4 +85,4 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i * ``enabled``: Whether the managed content security policy is enabled * ``sts``: Whether to additionally send a `Strict-Transport-Security` header * ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent -* ``ct_max_age``: The maximum age for the `Except-CT` header if sent +* ``ct_max_age``: The maximum age for the `Expect-CT` header if sent From fe67665e19cc98faff4a8ee53a3f4ca4190ca2ef Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:08:02 +0000 Subject: [PATCH 10/12] rename CSPPlug to HTTPSecurityPlug. --- config/config.exs | 2 +- config/config.md | 2 +- .../plugs/{csp_plug.ex => http_security_plug.ex} | 10 +++++----- lib/pleroma/web/endpoint.ex | 2 +- ...p_plug_test.exs => http_security_plug_test.exs} | 14 +++++++------- 5 files changed, 15 insertions(+), 15 deletions(-) rename lib/pleroma/plugs/{csp_plug.ex => http_security_plug.ex} (82%) rename test/plugs/{csp_plug_test.exs => http_security_plug_test.exs} (84%) diff --git a/config/config.exs b/config/config.exs index 1d918919d..be9c03ceb 100644 --- a/config/config.exs +++ b/config/config.exs @@ -176,7 +176,7 @@ limit: 23, web: "https://vinayaka.distsn.org/?{{host}}+{{user}}" -config :pleroma, :csp, +config :pleroma, :http_security, enabled: true, sts: false, sts_max_age: 31_536_000, diff --git a/config/config.md b/config/config.md index 446b0ce67..48af1c236 100644 --- a/config/config.md +++ b/config/config.md @@ -81,7 +81,7 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i * ``outgoing_blocks``: Whether to federate blocks to other instances * ``deny_follow_blocked``: Whether to disallow following an account that has blocked the user in question -## :csp +## :http_security * ``enabled``: Whether the managed content security policy is enabled * ``sts``: Whether to additionally send a `Strict-Transport-Security` header * ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/http_security_plug.ex similarity index 82% rename from lib/pleroma/plugs/csp_plug.ex rename to lib/pleroma/plugs/http_security_plug.ex index 8fc21b909..8d652a2f3 100644 --- a/lib/pleroma/plugs/csp_plug.ex +++ b/lib/pleroma/plugs/http_security_plug.ex @@ -1,14 +1,14 @@ -defmodule Pleroma.Plugs.CSPPlug do +defmodule Pleroma.Plugs.HTTPSecurityPlug do alias Pleroma.Config import Plug.Conn def init(opts), do: opts def call(conn, options) do - if Config.get([:csp, :enabled]) do + if Config.get([:http_security, :enabled]) do conn = merge_resp_headers(conn, headers()) - |> maybe_send_sts_header(Config.get([:csp, :sts])) + |> maybe_send_sts_header(Config.get([:http_security, :sts])) else conn end @@ -44,8 +44,8 @@ defp csp_string do end defp maybe_send_sts_header(conn, true) do - max_age_sts = Config.get([:csp, :sts_max_age]) - max_age_ct = Config.get([:csp, :ct_max_age]) + max_age_sts = Config.get([:http_security, :sts_max_age]) + max_age_ct = Config.get([:http_security, :ct_max_age]) merge_resp_headers(conn, [ {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 370d2d792..7783b8e5c 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.Endpoint do # You should set gzip to true if you are running phoenix.digest # when deploying your static files in production. plug(CORSPlug) - plug(Pleroma.Plugs.CSPPlug) + plug(Pleroma.Plugs.HTTPSecurityPlug) plug(Plug.Static, at: "/media", from: Pleroma.Uploaders.Local.upload_path(), gzip: false) diff --git a/test/plugs/csp_plug_test.exs b/test/plugs/http_security_plug_test.exs similarity index 84% rename from test/plugs/csp_plug_test.exs rename to test/plugs/http_security_plug_test.exs index e27b24db9..5268a1972 100644 --- a/test/plugs/csp_plug_test.exs +++ b/test/plugs/http_security_plug_test.exs @@ -1,10 +1,10 @@ -defmodule Pleroma.Web.Plugs.CSPPlugTest do +defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do use Pleroma.Web.ConnCase alias Pleroma.Config alias Plug.Conn test "it sends CSP headers when enabled", %{conn: conn} do - Config.put([:csp, :enabled], true) + Config.put([:http_security, :enabled], true) conn = conn @@ -20,7 +20,7 @@ test "it sends CSP headers when enabled", %{conn: conn} do end test "it does not send CSP headers when disabled", %{conn: conn} do - Config.put([:csp, :enabled], false) + Config.put([:http_security, :enabled], false) conn = conn @@ -36,8 +36,8 @@ test "it does not send CSP headers when disabled", %{conn: conn} do end test "it sends STS headers when enabled", %{conn: conn} do - Config.put([:csp, :enabled], true) - Config.put([:csp, :sts], true) + Config.put([:http_security, :enabled], true) + Config.put([:http_security, :sts], true) conn = conn @@ -48,8 +48,8 @@ test "it sends STS headers when enabled", %{conn: conn} do end test "it does not send STS headers when disabled", %{conn: conn} do - Config.put([:csp, :enabled], true) - Config.put([:csp, :sts], false) + Config.put([:http_security, :enabled], true) + Config.put([:http_security, :sts], false) conn = conn From ee5932a504d69e591aad7bdd52bd97d1f92d4e32 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:14:46 +0000 Subject: [PATCH 11/12] http security: allow referrer-policy to be configured --- config/config.exs | 3 ++- config/config.md | 1 + lib/pleroma/plugs/http_security_plug.ex | 4 +++- test/plugs/http_security_plug_test.exs | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/config/config.exs b/config/config.exs index be9c03ceb..9cc558564 100644 --- a/config/config.exs +++ b/config/config.exs @@ -180,7 +180,8 @@ enabled: true, sts: false, sts_max_age: 31_536_000, - ct_max_age: 2_592_000 + ct_max_age: 2_592_000, + referrer_policy: "same-origin" config :cors_plug, max_age: 86_400, diff --git a/config/config.md b/config/config.md index 48af1c236..5b4110646 100644 --- a/config/config.md +++ b/config/config.md @@ -86,3 +86,4 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i * ``sts``: Whether to additionally send a `Strict-Transport-Security` header * ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent * ``ct_max_age``: The maximum age for the `Expect-CT` header if sent +* ``referrer_policy``: The referrer policy to use, either `"same-origin"` or `"no-referrer"`. diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex index 8d652a2f3..960c7f6bf 100644 --- a/lib/pleroma/plugs/http_security_plug.ex +++ b/lib/pleroma/plugs/http_security_plug.ex @@ -15,12 +15,14 @@ def call(conn, options) do end defp headers do + referrer_policy = Config.get([:http_security, :referrer_policy]) + [ {"x-xss-protection", "1; mode=block"}, {"x-permitted-cross-domain-policies", "none"}, {"x-frame-options", "DENY"}, {"x-content-type-options", "nosniff"}, - {"referrer-policy", "same-origin"}, + {"referrer-policy", referrer_policy}, {"x-download-options", "noopen"}, {"content-security-policy", csp_string() <> ";"} ] diff --git a/test/plugs/http_security_plug_test.exs b/test/plugs/http_security_plug_test.exs index 5268a1972..55040a108 100644 --- a/test/plugs/http_security_plug_test.exs +++ b/test/plugs/http_security_plug_test.exs @@ -58,4 +58,20 @@ test "it does not send STS headers when disabled", %{conn: conn} do assert Conn.get_resp_header(conn, "strict-transport-security") == [] assert Conn.get_resp_header(conn, "expect-ct") == [] end + + test "referrer-policy header reflects configured value", %{conn: conn} do + conn = + conn + |> get("/api/v1/instance") + + assert Conn.get_resp_header(conn, "referrer-policy") == ["same-origin"] + + Config.put([:http_security, :referrer_policy], "no-referrer") + + conn = + build_conn() + |> get("/api/v1/instance") + + assert Conn.get_resp_header(conn, "referrer-policy") == ["no-referrer"] + end end From 2829fa41830ad8565fc186c3dc110f4d275f8827 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:17:04 +0000 Subject: [PATCH 12/12] sample config: chase http_security change --- lib/mix/tasks/sample_config.eex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index 824bc97a1..462c34636 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -26,7 +26,7 @@ config :pleroma, Pleroma.Repo, pool_size: 10 # Enable Strict-Transport-Security once SSL is working: -# config :pleroma, :csp, +# config :pleroma, :http_security, # sts: true # Configure S3 support if desired.