diff --git a/config/config.exs b/config/config.exs index 9a3cdcebf..dc709a592 100644 --- a/config/config.exs +++ b/config/config.exs @@ -453,10 +453,6 @@ config :pleroma, :media_preview_proxy, image_quality: 85, min_content_length: 100 * 1024 -config :pleroma, :shout, - enabled: true, - limit: 5_000 - config :phoenix, :format_encoders, json: Jason, "activity+json": Jason config :phoenix, :json_library, Jason @@ -796,6 +792,13 @@ config :pleroma, :web_cache_ttl, config :pleroma, :modules, runtime_dir: "instance/modules" config :pleroma, configurable_from_database: false +# Don't allow arbitrary module config here, you can only +# adjust our own config. +config :pleroma, + database_config_whitelist: [ + {:pleroma}, + {:logger} + ] config :pleroma, Pleroma.Repo, parameters: [gin_fuzzy_search_limit: "500"], diff --git a/docs/docs/configuration/cheatsheet.md b/docs/docs/configuration/cheatsheet.md index 73fdf9eea..b0aa6a2d5 100644 --- a/docs/docs/configuration/cheatsheet.md +++ b/docs/docs/configuration/cheatsheet.md @@ -375,6 +375,11 @@ This section describe PWA manifest instance-specific values. Currently this opti #### Pleroma.Web.MediaProxy.Invalidation.Script +!!! warning + Invalidation script options cannot be set in the database due to the ability to + set the command options to arbitrary paths. The following options **MUST** be + set in your `.exs` file instead. + This strategy allow perform external shell script to purge cache. Urls of attachments are passed to the script as arguments. @@ -1148,6 +1153,11 @@ Translations are available at `/api/v1/statuses/:id/translations/:language`, whe ### `:argos_translate` +!!! warning + Argos Translate options cannot be set in the database due to the ability to + set the command options to arbitrary paths. The following options **MUST** be + set in your `.exs` file instead. + - `:command_argos_translate` - command for `argos-translate`. Can be the command if it's in your PATH, or the full path to the file (default: `argos-translate`). - `:command_argospm` - command for `argospm`. Can be the command if it's in your PATH, or the full path to the file (default: `argospm`). - `:strip_html` - Strip html from the post before translating it (default: `true`). diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex index 831ba3b6f..24a925574 100644 --- a/lib/pleroma/web/admin_api/controllers/config_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/config_controller.ex @@ -9,6 +9,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do alias Pleroma.ConfigDB alias Pleroma.Web.Plugs.OAuthScopesPlug + @banned_in_db [ + # this would make no sense if you could change it in the db + {:pleroma, :database_config_whitelist}, + # called with System.cmd + {:pleroma, Pleroma.Web.MediaProxy.Invalidation.Script}, + {:pleroma, :argos_translate} + ] + plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update) @@ -175,17 +183,18 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do end defp whitelisted_config?(group, key) do - if whitelisted_configs = Config.get(:database_config_whitelist) do - Enum.any?(whitelisted_configs, fn + whitelisted = + :database_config_whitelist + |> Config.get([{:pleroma}]) + |> Enum.any?(fn {whitelisted_group} -> group == inspect(whitelisted_group) {whitelisted_group, whitelisted_key} -> group == inspect(whitelisted_group) && key == inspect(whitelisted_key) end) - else - true - end + + whitelisted && !disallowed_config?(group, key) end defp whitelisted_config?(%{group: group, key: key}) do @@ -195,4 +204,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do defp whitelisted_config?(%{group: group} = config) do whitelisted_config?(group, config[:key]) end + + defp disallowed_config?(group, key) do + Enum.any?(@banned_in_db, fn + {disallowed_group} -> + group == inspect(disallowed_group) + + {disallowed_group, disallowed_key} -> + group == inspect(disallowed_group) && key == inspect(disallowed_key) + end) + end end diff --git a/test/pleroma/web/admin_api/controllers/config_controller_test.exs b/test/pleroma/web/admin_api/controllers/config_controller_test.exs new file mode 100644 index 000000000..11264dbad --- /dev/null +++ b/test/pleroma/web/admin_api/controllers/config_controller_test.exs @@ -0,0 +1,95 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.ConfigControllerTest do + use Pleroma.Web.ConnCase, async: false + + import Pleroma.Factory + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + :ok + end + + setup do + clear_config(:configurable_from_database, true) + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + |> put_req_header("content-type", "application/json") + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "POST /api/v1/pleroma/admin/config" do + test "Refuses to update non-whitelisted config options", %{conn: conn} do + banned_config = %{ + configs: [ + %{ + group: ":mogrify", + key: ":mogrify_command", + value: [ + %{tuple: [":path", "sh"]}, + %{tuple: [":args", ["-c", "echo pwnd > /tmp/a"]]} + ] + } + ] + } + + clear_config([:database_config_whitelist], [{:pleroma}]) + + resp_that_should_not_work = + conn + |> post(~p"/api/v1/pleroma/admin/config", banned_config) + |> json_response_and_validate_schema(200) + + assert Enum.empty?(resp_that_should_not_work["configs"]) + + clear_config([:database_config_whitelist], [{:mogrify}]) + + resp_that_should_work = + conn + |> post(~p"/api/v1/pleroma/admin/config", banned_config) + |> json_response_and_validate_schema(200) + + refute Enum.empty?(resp_that_should_work["configs"]) + end + + test "Refuses to update strictly disallowed options", %{conn: conn} do + banned_config = %{ + configs: [ + %{ + group: ":pleroma", + key: ":database_config_whitelist", + value: [":pleroma"] + }, + %{ + group: ":pleroma", + key: ":argos_translate", + value: [ + %{tuple: [":command_argospm", "/opt/oepsiewoepsie"]} + ] + }, + %{ + group: ":pleroma", + key: "Pleroma.Web.MediaProxy.Invalidation.Script", + value: "wowee" + } + ] + } + + resp_that_should_not_work = + conn + |> post(~p"/api/v1/pleroma/admin/config", banned_config) + |> json_response_and_validate_schema(200) + + assert Enum.empty?(resp_that_should_not_work["configs"]) + end + end +end