diff options
| author | Dennis Fink | 2026-02-24 21:13:23 +0100 |
|---|---|---|
| committer | Dennis Fink | 2026-02-24 21:15:38 +0100 |
| commit | 63780c4c4b5a15b95631bab8abfe86fcd85fc9d0 (patch) | |
| tree | dd37714a9d4a18691f007fe1db335b5d434ad68a | |
| parent | ba036285523e557c79fa96f4e2529379c162cde8 (diff) | |
| download | transcode.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.
Diffstat (limited to '')
| -rwxr-xr-x | transcode.sh | 15 |
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=() |
