security: fix JSON injection in pulse module arguments

Use spa_json_encode_string to escape user-supplied strings before
inserting them into JSON configs in module-always-sink,
module-x11-bell, and module-switch-on-connect.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Wim Taymans 2026-04-29 17:56:12 +02:00
parent 7c2d8f7251
commit 344c9265a6
3 changed files with 33 additions and 15 deletions

View file

@ -2,6 +2,7 @@
/* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> */
/* SPDX-License-Identifier: MIT */
#include <spa/utils/json.h>
#include <pipewire/pipewire.h>
#include "../module.h"
@ -50,14 +51,17 @@ static int module_always_sink_load(struct module *module)
FILE *f;
char *args;
const char *str;
char encoded[1024];
size_t size;
if ((f = open_memstream(&args, &size)) == NULL)
return -errno;
fprintf(f, "{");
if ((str = pw_properties_get(module->props, "sink_name")) != NULL)
fprintf(f, " sink.name = \"%s\"", str);
if ((str = pw_properties_get(module->props, "sink_name")) != NULL) {
spa_json_encode_string(encoded, sizeof(encoded), str);
fprintf(f, " sink.name = %s", encoded);
}
fprintf(f, " }");
fclose(f);

View file

@ -135,11 +135,15 @@ static void manager_added(void *data, struct pw_manager_object *o)
/* Switch default */
pw_log_debug("switching to %s", name);
pw_manager_set_metadata(d->manager, d->metadata_default,
PW_ID_CORE,
pw_manager_object_is_sink(o) ? METADATA_CONFIG_DEFAULT_SINK
: METADATA_CONFIG_DEFAULT_SOURCE,
"Spa:String:JSON", "{ \"name\"\"%s\" }", name);
{
char encoded[1024];
spa_json_encode_string(encoded, sizeof(encoded), name);
pw_manager_set_metadata(d->manager, d->metadata_default,
PW_ID_CORE,
pw_manager_object_is_sink(o) ? METADATA_CONFIG_DEFAULT_SINK
: METADATA_CONFIG_DEFAULT_SOURCE,
"Spa:String:JSON", "{ \"name\" %s }", encoded);
}
}
static void manager_sync(void *data)

View file

@ -2,6 +2,7 @@
/* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> */
/* SPDX-License-Identifier: MIT */
#include <spa/utils/json.h>
#include <pipewire/pipewire.h>
#include "../module.h"
@ -58,20 +59,29 @@ static int module_x11_bell_load(struct module *module)
FILE *f;
char *args;
const char *str;
char encoded[1024];
size_t size;
if ((f = open_memstream(&args, &size)) == NULL)
return -errno;
fprintf(f, "{");
if ((str = pw_properties_get(module->props, "sink")) != NULL)
fprintf(f, " sink.name = \"%s\"", str);
if ((str = pw_properties_get(module->props, "sample")) != NULL)
fprintf(f, " sample.name = \"%s\"", str);
if ((str = pw_properties_get(module->props, "display")) != NULL)
fprintf(f, " x11.display = \"%s\"", str);
if ((str = pw_properties_get(module->props, "xauthority")) != NULL)
fprintf(f, " x11.xauthority = \"%s\"", str);
if ((str = pw_properties_get(module->props, "sink")) != NULL) {
spa_json_encode_string(encoded, sizeof(encoded), str);
fprintf(f, " sink.name = %s", encoded);
}
if ((str = pw_properties_get(module->props, "sample")) != NULL) {
spa_json_encode_string(encoded, sizeof(encoded), str);
fprintf(f, " sample.name = %s", encoded);
}
if ((str = pw_properties_get(module->props, "display")) != NULL) {
spa_json_encode_string(encoded, sizeof(encoded), str);
fprintf(f, " x11.display = %s", encoded);
}
if ((str = pw_properties_get(module->props, "xauthority")) != NULL) {
spa_json_encode_string(encoded, sizeof(encoded), str);
fprintf(f, " x11.xauthority = %s", encoded);
}
fprintf(f, " }");
fclose(f);