rm -rf on an Empty Variable — JavaScript Bug Hunt

Modelled on the Steam for Linux bug (January 2015): an uninstall script ran rm -rf "$STEAMROOT/".

  • Language: JavaScript
  • Layer: Backend
  • Difficulty: Easy
  • Concepts: Shell Safety, Empty Values
  • Modelled on: Steam for Linux · 2015
  • Visible tests: a normal root builds a path; an empty root is refused
  • Reward: 50 XP for a complete fix

Briefing

Modelled on the Steam for Linux bug (January 2015): an uninstall script ran rm -rf "$STEAMROOT/"*. When STEAMROOT was empty the expansion became rm -rf "/"*, and users lost everything the account could write, including mounted backup drives.

uninstall.js builds the same kind of path and never checks that the root is real.

Fix buildRemovePath so an empty, missing or root value is refused.

Bug report

BUG-STEAMROOT · Priority: Critical (data loss) · Reported by: linux support

buildRemovePath(root, subdir) must return:

  • { safe: true, path: root + "/" + subdir } for a sane absolute root
  • { safe: false, path: "" } when root is empty, undefined, "/" or does not start with "/"

Observed: an empty root produces "/steamapps" — and callers happily recurse from the filesystem root.

Logs

[uninstall] removing "/*" (STEAMROOT was empty)
[uninstall] 1.4 TB removed from an external mount

The code as shipped

src/installer/uninstall.js (editable)

// Builds the directory the uninstaller will remove.
exports.buildRemovePath = function (root, subdir) {
  return { safe: true, path: root + "/" + subdir };
};

Read-only context: src/installer/SAFETY.js.

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.