From 89c33fee5c51882c0f797a1c3b694a0700506001 Mon Sep 17 00:00:00 2001
From: "Jory A. Pratt" <geekypenguin@gmail.com>
Date: Sun, 15 Feb 2026 21:57:20 -0600
Subject: [PATCH 5/8] security: use escapeshellarg instead of escapeshellcmd,
 escape temp paths

- Replace escapeshellcmd with escapeshellarg per-argument (announcement,
  run_announcement, globalplay, piper_generate)
- Escape tempfile in exec() for toggle_cron, delete_announcement,
  update_announcement
---
 announcement.php        |  9 +++++----
 delete_announcement.php |  2 +-
 globalplay.php          |  2 +-
 piper_generate.php      | 12 +-----------
 run_announcement.php    |  4 ++--
 toggle_cron.php         |  2 +-
 update_announcement.php |  2 +-
 7 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/announcement.php b/announcement.php
index 94af151..0aac4d9 100644
--- a/announcement.php
+++ b/announcement.php
@@ -52,7 +52,7 @@ if (!is_executable($CONVERT_SCRIPT)) {
 }
 
 // Run conversion
-$cmd_convert = escapeshellcmd("$CONVERT_SCRIPT $src_mp3");
+$cmd_convert = $CONVERT_SCRIPT . ' ' . escapeshellarg($src_mp3);
 exec($cmd_convert, $output, $ret);
 if ($ret !== 0) {
     die("Conversion failed. Output: " . implode("\n", $output));
@@ -68,15 +68,16 @@ if (!file_exists($ul_file)) {
 }
 
 // Copy .ul file to Asterisk sounds directory
-$cmd_copy = escapeshellcmd("sudo cp $ul_file $SOUNDS_DIR/$base_name.ul");
+$dest_ul = $SOUNDS_DIR . '/' . $base_name . '.ul';
+$cmd_copy = 'sudo cp ' . escapeshellarg($ul_file) . ' ' . escapeshellarg($dest_ul);
 exec($cmd_copy, $copy_out, $copy_ret);
 if ($copy_ret !== 0) {
     die("Failed to copy $ul_file to $SOUNDS_DIR. Check sudo permissions.");
 }
 
 // Set proper permissions and ownership
-exec(escapeshellcmd("sudo chmod 644 $SOUNDS_DIR/$base_name.ul"));
-exec(escapeshellcmd("sudo chown root:root $SOUNDS_DIR/$base_name.ul"));
+exec('sudo chmod 644 ' . escapeshellarg($dest_ul));
+exec('sudo chown root:root ' . escapeshellarg($dest_ul));
 
 // Install cron job if scheduling info provided
 if ($min !== '' && $hour !== '' && $dom !== '' && $month !== '' && $dow !== '') {
diff --git a/delete_announcement.php b/delete_announcement.php
index e22a0c0..0304fa9 100644
--- a/delete_announcement.php
+++ b/delete_announcement.php
@@ -53,7 +53,7 @@ while ($i < count($new_lines)) {
 $tempfile = tempnam(sys_get_temp_dir(), 'cron_clean_');
 file_put_contents($tempfile, implode(PHP_EOL, $final_lines) . PHP_EOL);
 
-exec("sudo crontab $tempfile");
+exec('sudo crontab ' . escapeshellarg($tempfile));
 unlink($tempfile);
 
 echo "Cron Entry deleted Successfully.";
diff --git a/globalplay.php b/globalplay.php
index 9eb7614..a93efc2 100644
--- a/globalplay.php
+++ b/globalplay.php
@@ -30,7 +30,7 @@ if (!is_executable($play_script)) {
     exit;
 }
 
-$cmd = escapeshellcmd("sudo $play_script $play_path");
+$cmd = 'sudo ' . escapeshellarg($play_script) . ' ' . escapeshellarg($play_path);
 
 exec($cmd . " 2>&1", $output, $retval);
 
diff --git a/piper_generate.php b/piper_generate.php
index fcdd5ae..2fa5c84 100644
--- a/piper_generate.php
+++ b/piper_generate.php
@@ -47,17 +47,7 @@ $script = "/usr/local/bin/piper_prompt_tts.sh";
 
 // Build safe command with voice as third argument
 
-$cmd = escapeshellcmd(
-
-    "sudo $script " .
-
-    escapeshellarg($text) . " " .
-
-    escapeshellarg($filename) . " " .
-
-    escapeshellarg($voice)
-
-);
+$cmd = 'sudo ' . escapeshellarg($script) . ' ' . escapeshellarg($text) . ' ' . escapeshellarg($filename) . ' ' . escapeshellarg($voice);
 
 
 exec($cmd . " 2>&1", $output, $retval);
diff --git a/run_announcement.php b/run_announcement.php
index 6efb552..ae89cd1 100644
--- a/run_announcement.php
+++ b/run_announcement.php
@@ -49,8 +49,8 @@ if (!is_executable($play_script)) {
 }
 
 // Build and execute command
-$cmd = escapeshellcmd("sudo $play_script " . escapeshellarg($play_path));
-exec($cmd . " 2>&1", $output, $retval);
+$cmd = 'sudo ' . escapeshellarg($play_script) . ' ' . escapeshellarg($play_path);
+exec($cmd . ' 2>&1', $output, $retval);
 
 if ($retval === 0) {
     echo $echo_msg;
diff --git a/toggle_cron.php b/toggle_cron.php
index d027266..7be8fec 100644
--- a/toggle_cron.php
+++ b/toggle_cron.php
@@ -64,7 +64,7 @@ if (!$found) {
 $tempfile = tempnam(sys_get_temp_dir(), 'cron');
 file_put_contents($tempfile, implode("\n", $new_crontab) . "\n");
 
-exec("sudo crontab $tempfile", $out, $ret);
+exec('sudo crontab ' . escapeshellarg($tempfile), $out, $ret);
 unlink($tempfile);
 
 if ($ret === 0) {
diff --git a/update_announcement.php b/update_announcement.php
index a4353e8..aac6bf9 100644
--- a/update_announcement.php
+++ b/update_announcement.php
@@ -125,7 +125,7 @@ if (!$found) {
 $tempfile = tempnam(sys_get_temp_dir(), 'cron_update_');
 file_put_contents($tempfile, implode("\n", $new_crontab) . "\n");
 
-exec("sudo crontab $tempfile", $out, $ret);
+exec('sudo crontab ' . escapeshellarg($tempfile), $out, $ret);
 unlink($tempfile);
 
 if ($ret === 0) {
-- 
2.47.3

