Search code examples
bashpathfindrelative-pathsanitization

Sanitize $PATH for find -execdir


find -execdir is recommended over -exec, which the manual says has unavoidable security issues, and lists in the bugs section.

man find says regarding -execdir:

If you use this option, you must ensure that your $PATH environment variable does not reference .; otherwise, an attacker can run any commands they like by leaving an appropriately- named file in a directory in which you will run -execdir. The same applies to having entries in $PATH which are empty or which are not absolute directory names.

In a bash script, how does one comply with the manual's "must" and remove all relative or empty elements from $PATH?


Solution

  • You can sanitize your PATH using the following bash function:

    sanitize_PATH()
    {
        local new_path=""
        local dir
        while read -r -d: dir
        do
            if [[ $dir == /* ]]
            then
                new_path="$new_path:$dir"
            else
                echo "dropping from PATH: '$dir'"
            fi
        done <<< "$PATH:"
        PATH="${new_path#:}"
        echo PATH="$PATH"
    }
    

    Testing:

    $ PATH=/usr/local/bin:/usr/bin:/bin       sanitize_PATH
    PATH=/usr/local/bin:/usr/bin:/bin
    
    $ PATH=:/usr/local/bin:/usr/bin:/bin      sanitize_PATH
    dropping from PATH: ''
    PATH=/usr/local/bin:/usr/bin:/bin
    
    $ PATH=/usr/local/bin:/usr/bin:/bin:      sanitize_PATH
    dropping from PATH: ''
    PATH=/usr/local/bin:/usr/bin:/bin
    
    $ PATH=/usr/local/bin:/usr/bin:/bin:      sanitize_PATH
    dropping from PATH: ''
    PATH=/usr/local/bin:/usr/bin:/bin
    
    $ PATH=.:bin:/usr/local/bin:/usr/bin:/bin sanitize_PATH
    dropping from PATH: '.'
    dropping from PATH: 'bin'
    PATH=/usr/local/bin:/usr/bin:/bin
    
    $ PATH=/usr/local/bin::/usr/bin:/bin      sanitize_PATH
    dropping from PATH: ''
    PATH=/usr/local/bin:/usr/bin:/bin