aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Fink2026-02-24 21:13:23 +0100
committerDennis Fink2026-02-24 21:15:38 +0100
commit63780c4c4b5a15b95631bab8abfe86fcd85fc9d0 (patch)
treedd37714a9d4a18691f007fe1db335b5d434ad68a
parentba036285523e557c79fa96f4e2529379c162cde8 (diff)
downloadtranscode.sh-63780c4c4b5a15b95631bab8abfe86fcd85fc9d0.tar.gz
transcode.sh-63780c4c4b5a15b95631bab8abfe86fcd85fc9d0.zip
fix(preset): refuse to source world-writable preset files
Preset files are executed as shell code. A world-writable preset file could be modified by any local user to inject arbitrary commands. Symlinks are resolved before the permission check because stat on a symlink returns the permissions of the link itself (always 777 on Linux) rather than those of the target. readlink -f is used with a fallback to realpath for macOS/BSD compatibility.
-rwxr-xr-xtranscode.sh15
1 files changed, 15 insertions, 0 deletions
diff --git a/transcode.sh b/transcode.sh
index 7a0a9cb..15dba25 100755
--- a/transcode.sh
+++ b/transcode.sh
@@ -381,6 +381,21 @@ load_preset() {
debug "Sourcing preset file:" "$file"
+ # Reject preset files that are world-writable to prevent arbitrary users
+ # from injecting shell code.
+ #
+ # Symlinks must be resolved first: stat on a symlink returns the permissions
+ # of the symlink itself (always 777 on Linux), not the target. We use
+ # readlink -f (GNU) with a fallback to realpath for macOS/BSD.
+ local resolved_file
+ resolved_file=$(readlink -f -- "$file" 2>/dev/null || realpath -- "$file")
+ local preset_perms
+ preset_perms=$(stat -c '%a' -- "$resolved_file" 2>/dev/null || stat -f '%OLp' -- "$resolved_file")
+ if [[ "${preset_perms: -1}" =~ [2367] ]]; then
+ error "Preset file is world-writable, refusing to source:" "$resolved_file"
+ exit $EXIT_CONFIG_ERROR
+ fi
+
unset -v ffargs
ffargs=()