Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

It's because rm -rf "$STEAMROOT/"* will evaluate as rm -rf "/"* if $STEAMROOT for some reason is blank or unset, which is what happened here. (As someone in that discussion mentioned, a little more Bash knowledge might have suggested using rm -rf "${STEAMROOT:?}/"* instead, to force it to (at least) error if it is empty or unset.)


sort by: page size:

That's why I always use :? with rm in bash scripts. eg

    rm -rf "${STEAMROOT:?}/"*
Will exit with error instead of running rm if STEAMROOT is unset. Even if used inside a conditional.

> Would this have stopped things getting deleted?

No. "${STEAMROOT}" will contain something when the "rm" command runs. It just might not be what's expected.

> STEAMROOT="$(cd "${0%/*}" && echo $PWD)"


   rm -rf "$STEAMROOT/"*
This is why serious bash scripts use

   set -u # trap uses of unset variables
Won't help with deliberately blank ones, of course.

Scripting languages in which all variables are defined if you so much as breathe their names are such a scourge ...

I did this once in a build script. It wiped out all of /usr/lib. Of course, it was running as root! That machine was saved by a sysadmin who had a similar installation; we copied some libs from his machine and everything was cool.


Agreed, I should've elaborated. All it takes is something like this in the init script without checking if the variable is empty:

    rm -rf "$STEAMROOT/"*

  rm -rf "$STEAMROOT/"*
Yes. I have bookmarked this issue as a reminder to always read every single shell script before execution.

But why would the script prompt for user input unless something was awry? Presumably they control the contents of $STEAMROOT, so I don't see why rm -r should prompt unless it's about to do the wrong thing.

From reddit:

> It's actually rm -rf /bin.

> Seems to be caused by the same reason as the famous Steam bug - using an undefined variable. Plus the default bash behavior that simply ignores the fact that it doesn't exist and treats it like an empty string.

> tl;dr flamebait: The Unix way™ of "everything is just text" strikes again. (EDIT: yes this a gross over-generalization)

source: https://www.reddit.com/r/programming/comments/610z2f/858521_...


This is about the third time this has happened in this thread. What's the reason for writing the final "/" and not just `rm -rf $(SOME_TEMP_DIR)`?

GNU rm only catches "/". The Steam issue was for /* which is expanded by the shell.

That one doesn't work on systems which disallow deleting `/` unless you pass `--no-preserve-root`. But `rm -rf `${VARIABLE}/*` still does, and that's what steam did.

My teammate a couple years ago was writing a script that needed to clear a working directory, so `rm -rf $path/*`. He ran it during debugging and found one mistake - at some point the $path variable came in empty......

I once did

    rm -rf $PREFIX/usr/lib
in a Bash script being run as root. PREFIX was misspelled, and set -u was not in effect, so the misspelled variable silently expanded to nothing ...

rm -rf -- $EMPTY_VAR/*

Ooops.


Nobody mentions that 'rm -rf' is considered dangerous due to frequent problems in variable substitution when done in scripts and such: this is the most common source of issues with it afaik (eg. 'rm -rf /$mypath' will nuke everything if mypath is empty).

    # Scary!
    rm -rf "$STEAMROOT/"*
Anybody who writes a line like this deserves their software engineer license revoked. This isn't the first time I've seen shit like this (I've seen it in scripts expected to be run as root, no less); it makes my blood boil.

Seriously. "xargs rm -df -- < MANIFEST" is not that hard.

EDIT: I shouldn't be so harsh, if it weren't for the comment admitting knowing how poor an idea this line is.


Wow, nounset or not, doing a `rm -rf` on a variable without any check is quite irresponsible. Especially if they expect the script to be run as sudo.

or perhaps it was the dreaded "rm -rf ${DIR}/*" when $DIR is not defined.

The Steam line was more like ` rm -rf $VAR/* `, eg, they didn't want to delete the $VAR directory. Still, ` rm -rf /* ` is no fun.

This question that went unanswered in the replies bears repeating:

Any idea why the command actually ran? If $foo and $bar were both undefined, rm -rf / should have errored out with the --no-preserve-root message.

The only way I can think of that this would have actually worked on a CentOS7 machine is if $bar evaluated to , so what was run was rm -rf /.

As the above notes, I'm pretty sure recent versions of Redhat/CentOS actually protect against this sort of thing.

On the offchance you're not running a recent server, however, this could also be avoided by using `set -u` in the bash script, as it would cause undefined variables to error out.

next

Legal | privacy