Skip to content

fix: reject empty paths to prevent accidental cwd deletion - #342

Closed
abhu85 wants to merge 1 commit into
isaacs:mainfrom
abhu85:fix/empty-path-validation
Closed

abhu85 wants to merge 1 commit into
isaacs:mainfrom
abhu85:fix/empty-path-validation

Conversation

@abhu85

@abhu85 abhu85 commented Feb 23, 2026 •

Copy link
Copy Markdown

Summary

Fixes #326

When an empty string is passed to rimraf (e.g., rimrafSync('')), path.resolve('') returns the current working directory, causing rimraf to delete all files in cwd. This is extremely dangerous behavior that has caused real data loss for users.

The Problem

const { rimrafSync } = require('rimraf')
rimrafSync('')  // Deletes entire current working directory! 😱

The issue is that resolve('') returns process.cwd(), so the empty string silently becomes a valid path pointing to the current directory.

The Fix

This PR adds validation to reject empty strings and whitespace-only paths before they are resolved, throwing a clear ERR_INVALID_ARG_VALUE error:

rimrafSync('')     // TypeError: path cannot be empty
rimrafSync('   ')  // TypeError: path cannot be empty
rimrafSync('\t\n') // TypeError: path cannot be empty

Changes

  • src/path-arg.ts: Add empty/whitespace path validation before resolve() call
  • test/path-arg.ts: Add tests for empty string, spaces-only, and tabs/newlines

Test Results

All 31 path-arg tests pass (6 new tests added):

# { total: 31, pass: 31 }

@isaacs

isaacs commented Feb 23, 2026 •

Copy link
Copy Markdown
Owner

How is rimraf to know that this is accidental cwd removal, and not intentional cwd removal?

I suppose it's fair to just mimic what Node does, which we can do by just not resolving the paths in the first place before passing them to the implementation. However, "mimic what node does" gets tricky when looking at the other implementations.

For example:

  • fs.rmSync('.', { recursive: true, force: true }) Raises an error, but only after deleting the contents of the cwd (strange code, -4094, syscall: 'rm').
  • fs.rmSync('', { recursive: true }) Raises an error immediately (lstat('') ENOENT failure). If force: true is provided, then it silently does nothing.
  • fs.rmSync(process.cwd(), { recursive: true, force: true }) Raises no error, deletes the CWD.
  • fs.rmSync('a/.', { recursive: true, force: true }) raises that same -4094 error, but with the invalid path as a/.
  • fs.rmSync('a/b/../.', { recursive: true, force: true }) raises no error, deletes a contents, but not a itself, even though a/b/../. resolves to a (!?)
  • fs.rmSync('a/../.', { recursive: true, force: true }) Removes a and its contents, even though a/../. resolves to the cwd (!?)

Deleting whitespace-only paths must continue to be supported, how else would you delete a file named ' ' or '\t'? (Both of these are valid path names on Windows and Unix systems!)

So, I think there's some fixing to be done here, but this PR goes too far. I'll take a look in the coming days. In all cases, rimraf should either mimic Node's behavior, or we should send a PR to node to fix fs.rm if it's incorrect.

@abhu85

abhu85 commented Feb 23, 2026

Copy link
Copy Markdown
Author

Thank you for the detailed analysis! You're absolutely right that:

  1. Whitespace-only paths like ' ' or '\t' are valid filenames and must be supported
  2. The behavior should match Node's fs.rm (or Node should be fixed if incorrect)
  3. The edge cases you found with . and .. resolution are interesting inconsistencies

I'll leave this for you to handle since you have the full context on what rimraf's behavior should be. Happy to help if you'd like me to work on a revised approach after you've had a chance to investigate.

Based on maintainer feedback:
- Whitespace-only paths like ' ' or '\t' are valid filenames
- Only reject empty string '' to prevent cwd deletion
- Updated tests to verify whitespace paths resolve correctly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@abhu85
abhu85 force-pushed the fix/empty-path-validation branch from 5cb3ec8 to 6d77072 Compare February 23, 2026 17:50
@abhu85

abhu85 commented Feb 23, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed feedback @isaacs! You're absolutely right - whitespace paths are valid filenames.

I've updated the PR to:

  • Only reject empty string '' - prevents the resolve('') → cwd catastrophe
  • Allow whitespace paths like ' ' and '\t' - these are valid filenames that users should be able to delete
  • Updated tests to verify whitespace paths resolve correctly instead of throwing

The behavior now matches Node's approach more closely - only the literal empty string gets special handling.

@isaacs

isaacs commented Feb 25, 2026

Copy link
Copy Markdown
Owner

Once nodejs/node#61958 is fixed, I'll update rimraf to behave accordingly in all implementations.

@abhu85

abhu85 commented Mar 3, 2026

Copy link
Copy Markdown
Author

Thanks for filing the upstream issue. Since you'll be updating rimraf after nodejs/node#61958 is resolved, should I close this PR? Happy to do so if it's just adding noise.

@isaacs

isaacs commented Mar 4, 2026

Copy link
Copy Markdown
Owner

Yeah, I'm going to put up a PR to mirror the node behavior, and we can land it once that is finalized in Node, just to be sure it's the right approach.

Thanks for bringing this up :)

@isaacs isaacs closed this Mar 4, 2026
isaacs added a commit that referenced this pull request Mar 4, 2026
When removing any path that has `..` or `.` as path portions, call
`path.normalize` on the path before attempting to process it.

When removing the path `''`, throw a `stat ENOENT` error.

When removing `.`, replace with `process.cwd()` and proceed as normal.

Also, add support for deleting `file:` URLs and Buffer paths, which are
normalized to strings for the benefit of older Node versions.

Glob patters must still be normal `strings`.

This mirrors the behavior of node, once nodejs/node#61968 lands.

Closes: #342
Fixes: #326
Re: nodejs/node#61958
Credit: @abhu85, @RajeshKumar11, @isaacs
isaacs added a commit that referenced this pull request Mar 4, 2026
When removing any path that has `..` or `.` as path portions, call
`path.normalize` on the path before attempting to process it.

When removing the path `''`, throw a `stat ENOENT` error.

When removing `.`, replace with `process.cwd()` and proceed as normal.

Also, add support for deleting `file:` URLs and Buffer paths, which are
normalized to strings for the benefit of older Node versions.

Glob patterns must still be normal `strings`.

This mirrors the behavior of node, once nodejs/node#61968 lands.

Closes: #342
Fixes: #326
Re: nodejs/node#61958
Credit: @abhu85, @RajeshKumar11, @isaacs
isaacs added a commit that referenced this pull request Mar 4, 2026
When removing any path that has `..` or `.` as path portions, call
`path.normalize` on the path before attempting to process it.

When removing the path `''`, throw a `stat ENOENT` error.

When removing `.`, replace with `process.cwd()` and proceed as normal.

Also, add support for deleting `file:` URLs and Buffer paths, which are
normalized to `string` for the benefit of older Node versions.

Glob patterns must still be normal `string` values.

This mirrors the behavior of node, once nodejs/node#61968 lands.

Closes: #342
Fixes: #326
Re: nodejs/node#61958
Credit: @abhu85, @RajeshKumar11, @isaacs
@abhu85
abhu85 deleted the fix/empty-path-validation branch March 4, 2026 05:38
isaacs added a commit that referenced this pull request Mar 5, 2026
When removing any path that has `..` or `.` as path portions, call
`path.normalize` on the path before attempting to process it.

When removing the path `''`, throw a `stat ENOENT` error.

When removing `.`, replace with `process.cwd()` and proceed as normal.

Also, add support for deleting `file:` URLs and Buffer paths, which are
normalized to `string` for the benefit of older Node versions.

Glob patterns must still be normal `string` values.

This mirrors the behavior of node, once nodejs/node#61968 lands.

Closes: #342
Fixes: #326
Re: nodejs/node#61958
Credit: @abhu85, @RajeshKumar11, @isaacs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rimraf params validate problem

2 participants