Search code examples
bashshellrm

How to delete a folder by parameter and protect by user bugs/errors


Let's say I have in script something as following which get script input and delete that folder:

cd ` dirname "$0" `
X="${1}"
rm -rf ${X}/*

I see few bugs in this code:

  1. if the user sends / or something invalid - a rm -rf / will be executed.
  2. user can send .., ../.. and basically he can travel the folders.

A user is a developer in the company that uses this script, I'm not talking about hackers, client side requests etc. So mostly I'm talking about developer mistakes and lack of knowledge with what they are doing with this script.

I want to prevent rm -rf / scenario and anything delete which is not to a folder from the script location downwards.

How should I fix it?

I was thinking on something like:

cd ` dirname "$0" `
X="${1}"
rm -rf ./${X}/*

But even that is not closing the bug of.., and ../... I'm sure there is an elegant solution.


Solution

  • If you're only trying to avoid accidental mistakes, then one can keep it pretty simple. Assuming you have GNU readlink on your system:

    #!/usr/bin/env bash
    die() { echo "ERROR: $*" >&2; exit 1; }
    
    source_file=$(readlink -m -- "${BASH_SOURCE:-$0}")
    source_dir=${source_file%/*}
    dest_file=$(readlink -m -- "$1")
    
    [[ -e "$dest_file" ]] || die "Received argument '$dest_file', which does not exist"
    [[ $dest_file = "$source_dir"/* ]] || die "File must be under $source_dir"
    
    rm -rf -- "$dest_file"
    

    Because readlink -m tries to find the real, absolute path, it'll handle things like .. walking up the tree.