HTTP header improvements #294
13 changed files with 7 additions and 79 deletions
|
@ -487,8 +487,7 @@
|
||||||
config :pleroma, :http_security,
|
config :pleroma, :http_security,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sts: false,
|
sts: false,
|
||||||
sts_max_age: 31_536_000,
|
sts_max_age: 63_072_000,
|
||||||
ct_max_age: 2_592_000,
|
|
||||||
referrer_policy: "same-origin"
|
referrer_policy: "same-origin"
|
||||||
|
|
||||||
config :cors_plug,
|
config :cors_plug,
|
||||||
|
|
|
@ -1750,14 +1750,7 @@
|
||||||
label: "STS max age",
|
label: "STS max age",
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "The maximum age for the Strict-Transport-Security header if sent",
|
description: "The maximum age for the Strict-Transport-Security header if sent",
|
||||||
suggestions: [31_536_000]
|
suggestions: [63_072_000]
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :ct_max_age,
|
|
||||||
label: "CT max age",
|
|
||||||
type: :integer,
|
|
||||||
description: "The maximum age for the Expect-CT header if sent",
|
|
||||||
suggestions: [2_592_000]
|
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :referrer_policy,
|
key: :referrer_policy,
|
||||||
|
|
|
@ -453,7 +453,6 @@ This will make Akkoma listen on `127.0.0.1` port `8080` and generate urls starti
|
||||||
* ``enabled``: Whether the managed content security policy is enabled.
|
* ``enabled``: Whether the managed content security policy is enabled.
|
||||||
* ``sts``: Whether to additionally send a `Strict-Transport-Security` header.
|
* ``sts``: Whether to additionally send a `Strict-Transport-Security` header.
|
||||||
* ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent.
|
* ``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"`.
|
* ``referrer_policy``: The referrer policy to use, either `"same-origin"` or `"no-referrer"`.
|
||||||
* ``report_uri``: Adds the specified url to `report-uri` and `report-to` group in CSP header.
|
* ``report_uri``: Adds the specified url to `report-uri` and `report-to` group in CSP header.
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,13 @@ This will send additional HTTP security headers to the clients, including:
|
||||||
* `X-Permitted-Cross-Domain-Policies: "none"`
|
* `X-Permitted-Cross-Domain-Policies: "none"`
|
||||||
* `X-Frame-Options: "DENY"`
|
* `X-Frame-Options: "DENY"`
|
||||||
* `X-Content-Type-Options: "nosniff"`
|
* `X-Content-Type-Options: "nosniff"`
|
||||||
* `X-Download-Options: "noopen"`
|
|
||||||
|
|
||||||
A content security policy (CSP) will also be set:
|
A content security policy (CSP) will also be set:
|
||||||
|
|
||||||
```csp
|
```csp
|
||||||
content-security-policy:
|
content-security-policy:
|
||||||
default-src 'none';
|
default-src 'none';
|
||||||
base-uri 'self';
|
base-uri 'none';
|
||||||
frame-ancestors 'none';
|
frame-ancestors 'none';
|
||||||
img-src 'self' data: blob: https:;
|
img-src 'self' data: blob: https:;
|
||||||
media-src 'self' https:;
|
media-src 'self' https:;
|
||||||
|
@ -52,10 +51,6 @@ content-security-policy:
|
||||||
|
|
||||||
An additional “Strict transport security” header will be sent with the configured `sts_max_age` parameter. This tells the browser, that the domain should only be accessed over a secure HTTPs connection.
|
An additional “Strict transport security” header will be sent with the configured `sts_max_age` parameter. This tells the browser, that the domain should only be accessed over a secure HTTPs connection.
|
||||||
|
|
||||||
#### `ct_max_age`
|
|
||||||
|
|
||||||
An additional “Expect-CT” header will be sent with the configured `ct_max_age` parameter. This enforces the use of TLS certificates that are published in the certificate transparency log. (see [Expect-CT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT))
|
|
||||||
|
|
||||||
#### `referrer_policy`
|
#### `referrer_policy`
|
||||||
|
|
||||||
> Recommended value: `same-origin`
|
> Recommended value: `same-origin`
|
||||||
|
|
|
@ -160,7 +160,6 @@ server {
|
||||||
add_header X-Frame-Options DENY;
|
add_header X-Frame-Options DENY;
|
||||||
add_header X-Content-Type-Options nosniff;
|
add_header X-Content-Type-Options nosniff;
|
||||||
add_header Referrer-Policy same-origin;
|
add_header Referrer-Policy same-origin;
|
||||||
add_header X-Download-Options noopen;
|
|
||||||
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
|
|
@ -104,7 +104,6 @@ server {
|
||||||
add_header X-Frame-Options DENY;
|
add_header X-Frame-Options DENY;
|
||||||
add_header X-Content-Type-Options nosniff;
|
add_header X-Content-Type-Options nosniff;
|
||||||
add_header Referrer-Policy same-origin;
|
add_header Referrer-Policy same-origin;
|
||||||
add_header X-Download-Options noopen;
|
|
||||||
|
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
|
|
@ -165,10 +165,9 @@ http protocol plerup { # Protocol for upstream akkoma server
|
||||||
match response header append "X-Frame-Options" value "DENY"
|
match response header append "X-Frame-Options" value "DENY"
|
||||||
match response header append "X-Content-Type-Options" value "nosniff"
|
match response header append "X-Content-Type-Options" value "nosniff"
|
||||||
match response header append "Referrer-Policy" value "same-origin"
|
match response header append "Referrer-Policy" value "same-origin"
|
||||||
match response header append "X-Download-Options" value "noopen"
|
match response header append "Content-Security-Policy" value "default-src 'none'; base-uri 'none'; form-action 'self'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://CHANGEME.tld; upgrade-insecure-requests;" # Modify "CHANGEME.tld" and set your instance's domain here
|
||||||
match response header append "Content-Security-Policy" value "default-src 'none'; base-uri 'self'; form-action 'self'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://CHANGEME.tld; upgrade-insecure-requests;" # Modify "CHANGEME.tld" and set your instance's domain here
|
|
||||||
match request header append "Connection" value "upgrade"
|
match request header append "Connection" value "upgrade"
|
||||||
#match response header append "Strict-Transport-Security" value "max-age=31536000; includeSubDomains" # Uncomment this only after you get HTTPS working.
|
#match response header append "Strict-Transport-Security" value "max-age=63072000; includeSubDomains; preload" # Uncomment this only after you get HTTPS working.
|
||||||
|
|
||||||
# If you do not want remote frontends to be able to access your Akkoma backend server, comment these lines
|
# If you do not want remote frontends to be able to access your Akkoma backend server, comment these lines
|
||||||
match response header append "Access-Control-Allow-Origin" value "*"
|
match response header append "Access-Control-Allow-Origin" value "*"
|
||||||
|
|
|
@ -47,7 +47,6 @@ def headers do
|
||||||
{"x-frame-options", "DENY"},
|
{"x-frame-options", "DENY"},
|
||||||
{"x-content-type-options", "nosniff"},
|
{"x-content-type-options", "nosniff"},
|
||||||
{"referrer-policy", referrer_policy},
|
{"referrer-policy", referrer_policy},
|
||||||
{"x-download-options", "noopen"},
|
|
||||||
{"content-security-policy", csp_string()},
|
{"content-security-policy", csp_string()},
|
||||||
{"permissions-policy", "interest-cohort=()"}
|
{"permissions-policy", "interest-cohort=()"}
|
||||||
]
|
]
|
||||||
|
@ -76,7 +75,7 @@ def headers do
|
||||||
|
|
||||||
static_csp_rules = [
|
static_csp_rules = [
|
||||||
"default-src 'none'",
|
"default-src 'none'",
|
||||||
"base-uri 'self'",
|
"base-uri 'none'",
|
||||||
"frame-ancestors 'none'",
|
"frame-ancestors 'none'",
|
||||||
"style-src 'self' 'unsafe-inline'",
|
"style-src 'self' 'unsafe-inline'",
|
||||||
"font-src 'self'",
|
"font-src 'self'",
|
||||||
|
@ -237,11 +236,9 @@ def warn_if_disabled do
|
||||||
|
|
||||||
defp maybe_send_sts_header(conn, true) do
|
defp maybe_send_sts_header(conn, true) do
|
||||||
max_age_sts = Config.get([:http_security, :sts_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, [
|
merge_resp_headers(conn, [
|
||||||
{"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"},
|
{"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains; preload"}
|
||||||
{"expect-ct", "enforce, max-age=#{max_age_ct}"}
|
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1936,12 +1936,6 @@ msgstr ""
|
||||||
"What user agent to use. Must be a string or an atom `:default`. Default "
|
"What user agent to use. Must be a string or an atom `:default`. Default "
|
||||||
"value is `:default`."
|
"value is `:default`."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "config description at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "The maximum age for the Expect-CT header if sent"
|
|
||||||
msgstr "The maximum age for the Expect-CT header if sent"
|
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgctxt "config description at :pleroma-:http_security > :enabled"
|
msgctxt "config description at :pleroma-:http_security > :enabled"
|
||||||
|
@ -4993,12 +4987,6 @@ msgctxt "config label at :pleroma-:http > :user_agent"
|
||||||
msgid "User agent"
|
msgid "User agent"
|
||||||
msgstr "User agent"
|
msgstr "User agent"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "config label at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "CT max age"
|
|
||||||
msgstr "CT max age"
|
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgctxt "config label at :pleroma-:http_security > :enabled"
|
msgctxt "config label at :pleroma-:http_security > :enabled"
|
||||||
|
|
|
@ -1612,12 +1612,6 @@ msgctxt "config description at :pleroma-:http > :user_agent"
|
||||||
msgid "What user agent to use. Must be a string or an atom `:default`. Default value is `:default`."
|
msgid "What user agent to use. Must be a string or an atom `:default`. Default value is `:default`."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
msgctxt "config description at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "The maximum age for the Expect-CT header if sent"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
msgctxt "config description at :pleroma-:http_security > :enabled"
|
msgctxt "config description at :pleroma-:http_security > :enabled"
|
||||||
|
@ -4048,12 +4042,6 @@ msgctxt "config label at :pleroma-:http > :user_agent"
|
||||||
msgid "User agent"
|
msgid "User agent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
msgctxt "config label at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "CT max age"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
msgctxt "config label at :pleroma-:http_security > :enabled"
|
msgctxt "config label at :pleroma-:http_security > :enabled"
|
||||||
|
|
|
@ -1759,12 +1759,6 @@ msgstr ""
|
||||||
"What user agent to use. Must be a string or an atom `:default`. Default "
|
"What user agent to use. Must be a string or an atom `:default`. Default "
|
||||||
"value is `:default`."
|
"value is `:default`."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
|
||||||
msgctxt "config description at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "The maximum age for the Expect-CT header if sent"
|
|
||||||
msgstr "The maximum age for the Expect-CT header if sent"
|
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgctxt "config description at :pleroma-:http_security > :enabled"
|
msgctxt "config description at :pleroma-:http_security > :enabled"
|
||||||
|
@ -4420,12 +4414,6 @@ msgctxt "config label at :pleroma-:http > :user_agent"
|
||||||
msgid "User agent"
|
msgid "User agent"
|
||||||
msgstr "User agent"
|
msgstr "User agent"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
|
||||||
msgctxt "config label at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "CT max age"
|
|
||||||
msgstr "CT max age"
|
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgctxt "config label at :pleroma-:http_security > :enabled"
|
msgctxt "config label at :pleroma-:http_security > :enabled"
|
||||||
|
|
|
@ -1759,12 +1759,6 @@ msgstr ""
|
||||||
"What user agent to use. Must be a string or an atom `:default`. Default "
|
"What user agent to use. Must be a string or an atom `:default`. Default "
|
||||||
"value is `:default`."
|
"value is `:default`."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
|
||||||
msgctxt "config description at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "The maximum age for the Expect-CT header if sent"
|
|
||||||
msgstr "The maximum age for the Expect-CT header if sent"
|
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgctxt "config description at :pleroma-:http_security > :enabled"
|
msgctxt "config description at :pleroma-:http_security > :enabled"
|
||||||
|
@ -4420,12 +4414,6 @@ msgctxt "config label at :pleroma-:http > :user_agent"
|
||||||
msgid "User agent"
|
msgid "User agent"
|
||||||
msgstr "User agent"
|
msgstr "User agent"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
|
||||||
msgctxt "config label at :pleroma-:http_security > :ct_max_age"
|
|
||||||
msgid "CT max age"
|
|
||||||
msgstr "CT max age"
|
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgctxt "config label at :pleroma-:http_security > :enabled"
|
msgctxt "config label at :pleroma-:http_security > :enabled"
|
||||||
|
|
|
@ -17,7 +17,6 @@ test "it sends CSP headers when enabled", %{conn: conn} do
|
||||||
refute Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == []
|
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-frame-options") == []
|
||||||
refute Conn.get_resp_header(conn, "x-content-type-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, "referrer-policy") == []
|
||||||
refute Conn.get_resp_header(conn, "content-security-policy") == []
|
refute Conn.get_resp_header(conn, "content-security-policy") == []
|
||||||
end
|
end
|
||||||
|
@ -28,7 +27,6 @@ test "it sends STS headers when enabled", %{conn: conn} do
|
||||||
conn = get(conn, "/api/v1/instance")
|
conn = get(conn, "/api/v1/instance")
|
||||||
|
|
||||||
refute Conn.get_resp_header(conn, "strict-transport-security") == []
|
refute Conn.get_resp_header(conn, "strict-transport-security") == []
|
||||||
refute Conn.get_resp_header(conn, "expect-ct") == []
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it does not send STS headers when disabled", %{conn: conn} do
|
test "it does not send STS headers when disabled", %{conn: conn} do
|
||||||
|
@ -37,7 +35,6 @@ test "it does not send STS headers when disabled", %{conn: conn} do
|
||||||
conn = get(conn, "/api/v1/instance")
|
conn = get(conn, "/api/v1/instance")
|
||||||
|
|
||||||
assert Conn.get_resp_header(conn, "strict-transport-security") == []
|
assert Conn.get_resp_header(conn, "strict-transport-security") == []
|
||||||
assert Conn.get_resp_header(conn, "expect-ct") == []
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "referrer-policy header reflects configured value", %{conn: conn} do
|
test "referrer-policy header reflects configured value", %{conn: conn} do
|
||||||
|
@ -155,7 +152,6 @@ test "it does not send CSP headers when disabled", %{conn: conn} do
|
||||||
assert Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == []
|
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-frame-options") == []
|
||||||
assert Conn.get_resp_header(conn, "x-content-type-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, "referrer-policy") == []
|
||||||
assert Conn.get_resp_header(conn, "content-security-policy") == []
|
assert Conn.get_resp_header(conn, "content-security-policy") == []
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue