I'm currently writing a bash script that uses inotifywait
to perform certain actions on a user-supplied list of files and directories.
It has come to my attention that unlike a lot of shell tools, inotifywait
is unable to separate output records with \0
. This leaves the possibility of injection attacks with specifically crafted, but legal filenames (containing newlines).
I would like to work around this to ensure my script does not introduce any unnecessary vulnerabilities. My approach is as folllows:
- Ensure all files/paths passed for
inotifywait
to watch have trailing backslashes removed - Format
inotifywait
output with--format "%e %w%f//"
to produce output as follows:<EVENT LIST> <FILE PATH>//
- Pipe
inotifywait
output to sed; any//
found at the ends of lines with\0
- Use bash
while read
loop to read\0
-separated records - This means after the first record, all following records will have an extra leading newline. This is stripped off
- Each record may then be split at the first space - before the space is the event list (comma separated as per inotifywait) - and after the space the full pathname associated with the event
#!/bin/bash
shopt -s extglob
watchlist=("${@}")
# Remove trailing slashes from any watchlist elements
watchlist=("${watchlist[@]%%+(/)}")
# Reduce multiple consecutive slashes to singles as per @meuh
watchlist=("${watchlist[@]//+(\/)/\/}")
printf -vnewline "\n"
inotifywait -qrm "${watchlist[@]}" --format "%e %w%f//" | \
sed -u 's%//$%\x00%' | \
while IFS= read -r -d '' line; do
line="${line#${newline}}"
events="${line%% *}"
filepath="${line#* }"
printf "events=%s\nfilepath=%q\n" "$events" "$filepath"
done
As far as I can tell, this handles file/path names containing funny characters - spaces, newlines, quotes, etc. But it seems like a rather inelegant kludge.
For the purposes of this question, the ${watchlist[]}
array is just copied from command-line parameters, but this array may be build otherwise and may contain "funny" characters.
Are there any malicious paths that could break this? i.e. make the contents of the
$events
and$filepath
variables be incorrect for any given event?If this is water-tight, is there any cleaner way to do this?
Note I know I could easily write a c program to call inotify_add_watch()
and friends to get around this. But for now due to other dependencies I am working in bash.
I've been conflicted on whether to post this here or codereview.SE or even the main so.SE.