Skip to content

NIFI-15653 Fix DeleteSFTP security check for dot directory path#11266

Open
rakesh-rsky wants to merge 1 commit into
apache:mainfrom
rakesh-rsky:fix/NIFI-15653-delete-sftp-dot-path
Open

NIFI-15653 Fix DeleteSFTP security check for dot directory path#11266
rakesh-rsky wants to merge 1 commit into
apache:mainfrom
rakesh-rsky:fix/NIFI-15653-delete-sftp-dot-path

Conversation

@rakesh-rsky
Copy link
Copy Markdown
Contributor

@rakesh-rsky rakesh-rsky commented May 20, 2026

Summary

When the Remote Path property is configured as . (dot) — the default produced by ListSFTP — DeleteSFTP incorrectly routes every FlowFile to the failure relationship instead of deleting the file.

Root Cause

`java
final Path directoryPath = Paths.get(directoryPathProperty).normalize(); // "." → ""
final Path filePath = directoryPath.resolve(filename).normalize(); // "" + "test.txt" → "test.txt"

if (!directoryPath.equals(filePath.getParent())) { // "".equals(null) → false ← bug
`

Paths.get(".").normalize() returns an empty Path (""). Resolving a filename against that path yields a single-component relative path whose getParent() returns
ull. The check Paths.get("").equals(null) is always false, so the security guard fires incorrectly for every valid file.

Fix

java final Path fileParent = filePath.getParent(); if (!directoryPath.equals(fileParent == null ? Paths.get("") : fileParent)) {

When fileParent is
ull (single-component relative path), substitute Paths.get("") — the same empty-path value that directoryPath holds. Both represent the implicit current directory, so the check now passes correctly.

Path-traversal attempts (e.g. ../etc/passwd) still produce a non-empty parent that does not equal the empty directoryPath, so the security guard remains fully intact.

Testing

Added TestDeleteSFTP.deletesFileWhenDirectoryPathIsDot() using the existing embedded SSH server to confirm that a file in the root of the SFTP server is successfully deleted when the directory property is set to .(dot).

When the Remote Path property is set to '.' (as produced by ListSFTP),
Paths.get('.').normalize() returns an empty Path (''). Resolving a
filename against that empty path yields a single-component relative
path whose getParent() returns null, causing the directory-traversal
security check to fail incorrectly and route every FlowFile to the
failure relationship.

Fix: when fileParent is null (single-component relative path), substitute
Paths.get('') for the comparison. Both the empty normalized path and a
null parent represent the implicit current directory, so the check now
correctly passes. Path-traversal attempts (e.g. '../etc/passwd') still
produce a non-empty parent that does not equal the empty directoryPath,
so the security guard remains intact.

Add TestDeleteSFTP.deletesFileWhenDirectoryPathIsDot() to cover the
regression.
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.

1 participant