pleroma_ctl: Properly handle user arguments with whitespace

When user supplied arguments to pleroma_ctl include whitespace
that has been properly quoted, all arguments were sent to
ReleaseTasks in one string, which then String.split/1 the input on any
whitespace. This broke Mix tasks that accept certain user input like
instance gen and user management.

To fix this, pleroma_ctl now sends the arguments in list
form. Additionally pleroma_ctl arguments now need to be pre-processed.

Fixes pleroma/pleroma#7874
This commit is contained in:
Phantasm 2026-04-24 15:04:12 +02:00
commit 7f97e21910
No known key found for this signature in database
GPG key ID: 2669E588BCC634C8
2 changed files with 25 additions and 4 deletions

View file

@ -5,7 +5,10 @@
defmodule Pleroma.ReleaseTasks do defmodule Pleroma.ReleaseTasks do
@repo Pleroma.Repo @repo Pleroma.Repo
def run(args) do # TODO: Kept for some backwards compatibility with buggy pleroma_ctl,
# if a mismatch between pleroma_ctl and Pleroma accidentaly happens.
# Remove in the future.
def run(args) when is_binary(args) do
[task | args] = String.split(args) [task | args] = String.split(args)
case task do case task do
@ -16,6 +19,20 @@ defmodule Pleroma.ReleaseTasks do
end end
end end
# HACK: Script arguments need to be received as a list, otherwise (quoted) arguments with
# whitespace will be broken. Previously the broken string form above was used,
# escaping in the shell does not help.
def run(args) when is_list(args) do
[task | args] = args
case task do
"migrate" -> migrate(args)
"create" -> create()
"rollback" -> rollback(args)
task -> mix_task(task, args)
end
end
def find_module(task) do def find_module(task) do
module_name = module_name =
task task

View file

@ -137,7 +137,11 @@ else
SCRIPT=$(realpath "$0") SCRIPT=$(realpath "$0")
SCRIPTPATH=$(dirname "$SCRIPT") SCRIPTPATH=$(dirname "$SCRIPT")
FULL_ARGS="$*" # HACK: Script arguments need to be sent as an array to Mix tasks, otherwise they will break (quoted) arguments with whitespace.
# Previously it was sent as string, which would get split on whitespace on the task side.
# Escaping does not help including non-POSIX printf %q
PREPARED_ARGS=""
for arg in "$@"; do PREPARED_ARGS="$PREPARED_ARGS \"$arg\","; done
ACTION="$1" ACTION="$1"
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
@ -154,8 +158,8 @@ else
if [ "$ACTION" = "update" ]; then if [ "$ACTION" = "update" ]; then
update "$@" update "$@"
elif [ "$ACTION" = "migrate" ] || [ "$ACTION" = "rollback" ] || [ "$ACTION" = "create" ] || [ "$ACTION $SUBACTION" = "instance gen" ] || [ "$PLEROMA_CTL_RPC_DISABLED" = true ]; then elif [ "$ACTION" = "migrate" ] || [ "$ACTION" = "rollback" ] || [ "$ACTION" = "create" ] || [ "$ACTION $SUBACTION" = "instance gen" ] || [ "$PLEROMA_CTL_RPC_DISABLED" = true ]; then
"$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run("'"$FULL_ARGS"'")' "$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run(['"${PREPARED_ARGS%%,}"'])'
else else
"$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run("'"$FULL_ARGS"'")' "$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run(['"${PREPARED_ARGS%%,}"'])'
fi fi
fi fi