diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2cb39a5c9..ff3308e31 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -66,13 +66,21 @@ check-changelog:
- "**/*.exs"
- "mix.lock"
+.using-ci-base:
+ tags:
+ - amd64
+
build:
- extends: .build_changes_policy
+ extends:
+ - .build_changes_policy
+ - .using-ci-base
stage: build
script:
- mix compile --force
spec-build:
+ extends:
+ - .using-ci-base
stage: test
rules:
- changes:
@@ -86,6 +94,8 @@ spec-build:
- mix pleroma.openapi_spec spec.json
benchmark:
+ extends:
+ - .using-ci-base
stage: benchmark
when: manual
variables:
@@ -100,7 +110,9 @@ benchmark:
- mix pleroma.load_testing
unit-testing:
- extends: .build_changes_policy
+ extends:
+ - .build_changes_policy
+ - .using-ci-base
stage: test
cache: &testing_cache_policy
<<: *global_cache_policy
@@ -122,7 +134,9 @@ unit-testing:
path: coverage.xml
unit-testing-erratic:
- extends: .build_changes_policy
+ extends:
+ - .build_changes_policy
+ - .using-ci-base
stage: test
retry: 2
allow_failure: true
@@ -156,7 +170,9 @@ unit-testing-erratic:
# - mix test --trace --only federated
unit-testing-rum:
- extends: .build_changes_policy
+ extends:
+ - .build_changes_policy
+ - .using-ci-base
stage: test
cache: *testing_cache_policy
services:
@@ -187,7 +203,9 @@ lint:
- mix format --check-formatted
analysis:
- extends: .build_changes_policy
+ extends:
+ - .build_changes_policy
+ - .using-ci-base
stage: test
cache: *testing_cache_policy
script:
@@ -213,7 +231,7 @@ docs-deploy:
before_script:
- apk add curl
script:
- - curl -X POST -F"token=$DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline
+ - curl --fail-with-body -X POST -F"token=$CI_JOB_TOKEN" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline
review_app:
image: alpine:3.9
stage: deploy
@@ -254,7 +272,7 @@ spec-deploy:
before_script:
- apk add curl
script:
- - curl -X POST -F"token=$API_DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline
+ - curl --fail-with-body -X POST -F"token=$CI_JOB_TOKEN" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline
stop_review_app:
diff --git a/.gitlab/merge_request_templates/Release.md b/.gitlab/merge_request_templates/Release.md
index 9638d6d11..e57556e6c 100644
--- a/.gitlab/merge_request_templates/Release.md
+++ b/.gitlab/merge_request_templates/Release.md
@@ -1,6 +1,6 @@
### Release checklist
* [ ] Bump version in `mix.exs`
-* [ ] Compile a changelog
+* [ ] Compile a changelog with the `tools/collect-changelog` script
* [ ] Create an MR with an announcement to pleroma.social
#### post-merge
* [ ] Tag the release on the merge commit
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42a1bbb8f..394eb5179 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,19 +4,76 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-## Unreleased
-
-### Changed
+## 2.6.0
+### Security
+- Preload: Make generated JSON html-safe. It already was html safe because it only consists of config data that is base64 encoded, but this will keep it safe it that ever changes.
+- CommonAPI: Prevent users from accessing media of other users by creating a status with reused attachment ID
+- Disable XML entity resolution completely to fix a dos vulnerability
### Added
- Support for Image activities, namely from Hubzilla
+- Add OAuth scope descriptions
+- Allow lang attribute in status text
+- OnlyMedia Upload Filter
+- Implement MRF policy to reject or delist according to emojis
+- (hardening) Add no_new_privs=yes to OpenRC service files
+- Implement quotes
+- Add unified streaming endpoint
### Fixed
-
- rel="me" was missing its cache
+- MediaProxy responses now return a sandbox CSP header
+- Filter context activities using Visibility.visible_for_user?
+- UploadedMedia: Add missing disposition_type to Content-Disposition
+- fix not being able to fetch flash file from remote instance
+- Fix abnormal behaviour when refetching a poll
+- Allow non-HTTP(s) URIs in "url" fields for compatibility with "FEP-fffd: Proxy Objects"
+- Fix opengraph and twitter card meta tags
+- ForceMentionsInContent: fix double mentions for Mastodon/Misskey posts
+- OEmbed HTML tags are now filtered
+- Restrict attachments to only uploaded files only
+- Fix error 404 when deleting status of a banned user
+- Fix config ownership in dockerfile to pass restriction test
+- Fix user fetch completely broken if featured collection is not in a supported form
+- Correctly handle the situation when a poll has both "anyOf" and "oneOf" but one of them being empty
+- Fix handling report from a deactivated user
+- Prevent using the .json format to bypass authorized fetch mode
+- Fix mentioning punycode domains when using Markdown
+- Show more informative errors when profile exceeds char limits
### Removed
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
+- remove BBS/SSH feature, replaced by an external bridge.
+- Remove a few unused indexes.
+- Cleanup OStatus-era user upgrades and ap_enabled indicator
+- Deprecate Pleroma's audio scrobbling
+
+## 2.5.4
+
+## Security
+- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem
+
+## 2.5.3
+
+### Security
+- Emoji pack loader sanitizes pack names
+- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
+
+## 2.5.5
+
+## Security
+- Prevent users from accessing media of other users by creating a status with reused attachment ID
+
+## 2.5.4
+
+## Security
+- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem
+
+## 2.5.3
+
+### Security
+- Emoji pack loader sanitizes pack names
+- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
## 2.5.2
diff --git a/Dockerfile b/Dockerfile
index 56c99da72..d2a3e3573 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -49,7 +49,7 @@ USER pleroma
COPY --from=build --chown=pleroma:0 /release ${HOME}
-COPY ./config/docker.exs /etc/pleroma/config.exs
+COPY --chown=pleroma --chmod=640 ./config/docker.exs /etc/pleroma/config.exs
COPY ./docker-entrypoint.sh ${HOME}
EXPOSE 4000
diff --git a/README.md b/README.md
index 62f8fdc64..2837b6ef8 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,8 @@ If your platform is not supported, or you just want to be able to edit the sourc
- [OpenBSD (fi)](https://docs-develop.pleroma.social/backend/installation/openbsd_fi/)
### OS/Distro packages
-Currently Pleroma is packaged for [YunoHost](https://yunohost.org) and [NixOS](https://nixos.org). If you want to package Pleroma for any OS/Distros, we can guide you through the process on our [community channels](#community-channels). If you want to change default options in your Pleroma package, please **discuss it with us first**.
+Currently Pleroma is packaged for [YunoHost](https://yunohost.org), [NixOS](https://nixos.org), [Gentoo through GURU](https://gentoo.org/) and [Archlinux through AUR](https://aur.archlinux.org/packages/pleroma). You may find more at
+
diff --git a/docs/installation/otp_vs_from_source_source.include b/docs/installation/otp_vs_from_source_source.include
index 63482b69d..9f7134229 100644
--- a/docs/installation/otp_vs_from_source_source.include
+++ b/docs/installation/otp_vs_from_source_source.include
@@ -1,3 +1,3 @@
{! backend/installation/otp_vs_from_source.include !}
-This guide covers a from-source installation. To install using OTP releases, please check out [the OTP guide](./otp_en.md).
+This guide covers a manual from-source installation. To install using OTP releases, please check for the presence of a distro package, failing that you can use [Pleroma-provided OTP binaries](./otp_en.md).
diff --git a/installation/init.d/pleroma b/installation/init.d/pleroma
index 384536f7e..cb6635a0b 100755
--- a/installation/init.d/pleroma
+++ b/installation/init.d/pleroma
@@ -8,6 +8,7 @@ pidfile="/var/run/pleroma.pid"
directory=/opt/pleroma
healthcheck_delay=60
healthcheck_timer=30
+no_new_privs="yes"
: ${pleroma_port:-4000}
diff --git a/installation/pleroma-mediaproxy.nginx b/installation/pleroma-mediaproxy.nginx
new file mode 100644
index 000000000..6f2edf212
--- /dev/null
+++ b/installation/pleroma-mediaproxy.nginx
@@ -0,0 +1,97 @@
+# This file is for those who want to serve uploaded media and media proxy over
+# another domain. This is STRONGLY RECOMMENDED.
+# This is meant to be used ALONG WITH `pleroma.nginx`.
+
+# If this is a new instance, replace the `location ~ ^/(media|proxy)` section in
+# `pleroma.nginx` with the following to completely disable access to media from the main domain:
+# location ~ ^/(media|proxy) {
+# return 404;
+# }
+#
+# If you are configuring an existing instance to use another domain
+# for media, you will want to keep redirecting all existing local media to the new domain
+# so already-uploaded media will not break.
+# Replace the `location ~ ^/(media|proxy)` section in `pleroma.nginx` with the following:
+#
+# location /media {
+# return 301 https://some.other.domain$request_uri;
+# }
+#
+# location /proxy {
+# return 404;
+# }
+
+server {
+ server_name some.other.domain;
+
+ listen 80;
+ listen [::]:80;
+
+ # Uncomment this if you need to use the 'webroot' method with certbot. Make sure
+ # that the directory exists and that it is accessible by the webserver. If you followed
+ # the guide, you already ran 'mkdir -p /var/lib/letsencrypt' to create the folder.
+ # You may need to load this file with the ssl server block commented out, run certbot
+ # to get the certificate, and then uncomment it.
+ #
+ # location ~ /\.well-known/acme-challenge {
+ # root /var/lib/letsencrypt/;
+ # }
+ location / {
+ return 301 https://$server_name$request_uri;
+ }
+}
+
+server {
+ server_name some.other.domain;
+
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ ssl_session_timeout 1d;
+ ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
+ ssl_session_tickets off;
+
+ ssl_trusted_certificate /etc/letsencrypt/live/some.other.domain/chain.pem;
+ ssl_certificate /etc/letsencrypt/live/some.other.domain/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/some.other.domain/privkey.pem;
+
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
+ ssl_prefer_server_ciphers off;
+ # In case of an old server with an OpenSSL version of 1.0.2 or below,
+ # leave only prime256v1 or comment out the following line.
+ ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
+ ssl_stapling on;
+ ssl_stapling_verify on;
+
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_comp_level 6;
+ gzip_buffers 16 8k;
+ gzip_http_version 1.1;
+ gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;
+
+ # the nginx default is 1m, not enough for large media uploads
+ client_max_body_size 16m;
+ ignore_invalid_headers off;
+
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ location / { return 404; }
+
+ location ~ ^/(media|proxy) {
+ proxy_cache pleroma_media_cache;
+ slice 1m;
+ proxy_cache_key $host$uri$is_args$args$slice_range;
+ proxy_set_header Range $slice_range;
+ proxy_cache_valid 200 206 301 304 1h;
+ proxy_cache_lock on;
+ proxy_ignore_client_abort on;
+ proxy_buffering on;
+ chunked_transfer_encoding on;
+ proxy_pass http://phoenix;
+ }
+}
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index 5c93f19ff..5d8b254a2 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -266,12 +266,20 @@ defmodule Mix.Tasks.Pleroma.Instance do
config_dir = Path.dirname(config_path)
psql_dir = Path.dirname(psql_path)
+ # Note: Distros requiring group read (0o750) on those directories should
+ # pre-create the directories.
[config_dir, psql_dir, static_dir, uploads_dir]
|> Enum.reject(&File.exists?/1)
- |> Enum.map(&File.mkdir_p!/1)
+ |> Enum.each(fn dir ->
+ File.mkdir_p!(dir)
+ File.chmod!(dir, 0o700)
+ end)
shell_info("Writing config to #{config_path}.")
+ # Sadly no fchmod(2) equivalent in Elixir…
+ File.touch!(config_path)
+ File.chmod!(config_path, 0o640)
File.write(config_path, result_config)
shell_info("Writing the postgres script to #{psql_path}.")
File.write(psql_path, result_psql)
@@ -290,8 +298,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
else
shell_error(
"The task would have overwritten the following files:\n" <>
- (Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <>
- "Rerun with `--force` to overwrite them."
+ Enum.map_join(will_overwrite, &"- #{&1}\n") <> "Rerun with `--force` to overwrite them."
)
end
end
diff --git a/lib/pleroma/config/release_runtime_provider.ex b/lib/pleroma/config/release_runtime_provider.ex
index 91e5f1a54..9ec0f975e 100644
--- a/lib/pleroma/config/release_runtime_provider.ex
+++ b/lib/pleroma/config/release_runtime_provider.ex
@@ -20,6 +20,20 @@ defmodule Pleroma.Config.ReleaseRuntimeProvider do
with_runtime_config =
if File.exists?(config_path) do
+ #
#{quote_line}"
+ end
+
+ defp has_inline_quote?(content, quote_url) do
+ cond do
+ # Does the quote URL exist in the content?
+ content =~ quote_url -> true
+ # Does the content already have a .quote-inline span?
+ content =~ "" -> true
+ # No inline quote found
+ true -> false
+ end
+ end
+
+ defp filter_object(%{"quoteUrl" => quote_url} = object) do
+ content = object["content"] || ""
+
+ if has_inline_quote?(content, quote_url) do
+ object
+ else
+ template = Pleroma.Config.get([:mrf_inline_quote, :template])
+
+ content =
+ if String.ends_with?(content, "
You requested a full backup of your Pleroma account. It's ready for download:
\n\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:384 +#, elixir-autogen, elixir-format msgctxt "account archive email subject" msgid "Your account archive is ready" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:188 +#, elixir-autogen, elixir-format msgctxt "approval pending email body" msgid "Your account at %{instance_name} is being reviewed by staff. You will receive another email once your account is approved.
\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:202 +#, elixir-autogen, elixir-format msgctxt "approval pending email subject" msgid "Your account is awaiting approval" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:158 +#, elixir-autogen, elixir-format msgctxt "confirmation email body" msgid "Email confirmation is required to activate the account.
\nPlease click the following link to activate your account.
\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:174 +#, elixir-autogen, elixir-format msgctxt "confirmation email subject" msgid "%{instance_name} account confirmation" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:310 +#, elixir-autogen, elixir-format msgctxt "digest email subject" msgid "Your digest from %{instance_name}" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:81 +#, elixir-autogen, elixir-format msgctxt "password reset email body" msgid "Someone has requested password change for your account at %{instance_name}.
\nIf it was you, visit the following link to proceed: reset password.
\nIf it was someone else, nothing to worry about: your data is secure and your password has not been changed.
\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:98 +#, elixir-autogen, elixir-format msgctxt "password reset email subject" msgid "Password reset" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:215 +#, elixir-autogen, elixir-format msgctxt "successful registration email body" msgid "Your account at %{instance_name} has been registered successfully.
\nNo further action is required to activate your account.
\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:231 +#, elixir-autogen, elixir-format msgctxt "successful registration email subject" msgid "Account registered on %{instance_name}" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:119 +#, elixir-autogen, elixir-format msgctxt "user invitation email body" msgid "%{inviter_name} invites you to join %{instance_name}, an instance of Pleroma federated social networking platform.
\nClick the following link to register: accept invitation.
\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:136 +#, elixir-autogen, elixir-format msgctxt "user invitation email subject" msgid "Invitation to %{instance_name}" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:53 +#, elixir-autogen, elixir-format msgctxt "welcome email html body" msgid "Welcome to %{instance_name}!" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:41 +#, elixir-autogen, elixir-format msgctxt "welcome email subject" msgid "Welcome to %{instance_name}!" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:65 +#, elixir-autogen, elixir-format msgctxt "welcome email text body" msgid "Welcome to %{instance_name}!" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/emails/user_email.ex:368 +#, elixir-autogen, elixir-format msgctxt "account archive email body - admin requested" msgid "Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:
\n\n" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/twitter_api/controllers/util_controller.ex:123 +#, elixir-autogen, elixir-format msgctxt "remote follow error message - unknown error" msgid "Something went wrong." msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/twitter_api/controllers/util_controller.ex:67 +#, elixir-autogen, elixir-format msgctxt "remote follow error message - user not found" msgid "Could not find user" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:8 +#, elixir-autogen, elixir-format msgctxt "status interact authorization button" msgid "Interact" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:2 +#, elixir-autogen, elixir-format msgctxt "status interact error" msgid "Error: %{error}" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/twitter_api/controllers/util_controller.ex:95 +#, elixir-autogen, elixir-format msgctxt "status interact error message - status not found" msgid "Could not find status" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/twitter_api/controllers/util_controller.ex:144 +#, elixir-autogen, elixir-format msgctxt "status interact error message - unknown error" msgid "Something went wrong." msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:4 +#, elixir-autogen, elixir-format msgctxt "status interact header" msgid "Interacting with %{nickname}'s %{status_link}" msgstr "" -#, elixir-autogen, elixir-format #: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:4 +#, elixir-autogen, elixir-format msgctxt "status interact header - status link text" msgid "status" msgstr "" diff --git a/priv/repo/migrations/20221216052127_add_state_to_backups.exs b/priv/repo/migrations/20221216052127_add_state_to_backups.exs new file mode 100644 index 000000000..73b30fc35 --- /dev/null +++ b/priv/repo/migrations/20221216052127_add_state_to_backups.exs @@ -0,0 +1,21 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors