Cristian Amigo created VFS-865:
----------------------------------
Summary: [SFTP] File names containing '*' or '?' are passed to
JSch unescaped: delete() can remove other files, listing truncates names at '?'
Key: VFS-865
URL: https://issues.apache.org/jira/browse/VFS-865
Project: Commons VFS
Issue Type: Bug
Affects Versions: 2.10.0
Environment: SFTP provider, JSch 0.1.55 (also com.github.mwiede:jsch
2.28.7)
Reporter: Cristian Amigo
{{SftpFileObject}} passes the decoded relative path straight to
{{ChannelSftp}}. JSch expands {{*}} and {{?}} in the last path component of
{{rm}}, {{rmdir}}, {{stat}}, {{get}}, {{put}}, {{ls}}, {{cd}}, {{rename}} and
{{setStat}} (backslash is its escape character). So a VFS file whose name
contains one of these characters is handled as a glob pattern.
Observed on current master with the embedded Apache MINA SSHD test server. The
exception is the final {{delete()}} in item 2, which was observed with 2.10.0
against an {{atmoz/sftp}} (OpenSSH) server, together with item 1:
1. *delete() removes siblings.* In a folder with {{a*.txt}} and {{abc.txt}},
get {{a*.txt}} from {{getChildren()}} (or {{findFiles()}}) and call
{{delete()}}. Both files are deleted, because {{doDelete()}} calls
{{channel.rm(".../a*.txt")}}.
2. *A name resolves to another file.* In a folder with only {{delA.txt}},
{{resolveFile("del%3F.txt").exists()}} returns {{true}}:
{{stat(".../del?.txt")}} matches {{delA.txt}}. Then {{delete()}} removes
{{delA.txt}}.
3. *Read, write and rename fail.* Reading {{a*.txt}} next to {{abc.txt}} throws
{{a*.txt is not unique: [abc.txt, a*.txt]}}. Writing a new file {{new?.txt}}
fails ({{is not unique: []}}). Renaming {{a*.txt}} fails for the same reason.
4. *Listing a folder named {{d*}}* returns the siblings that match {{d*}}, not
the content of the folder. For the same reason an empty folder {{d*}} next to
{{dX}} cannot be deleted: it looks non-empty, so {{delete()}} returns {{false}}.
5. *Listing truncates names at {{?}}.* {{doListChildrenResolved()}} resolves
each child with {{UriParser.encode(name)}}, which only escapes {{%}}. The SFTP
file name parser then treats {{?}} as the start of a query string, so a child
named {{v2?final.txt}} is returned as {{v2}}.
Reproduction (embedded server, Linux or macOS; Windows file names cannot
contain these characters):
{code:java}
// server home contains: dir/a*.txt and dir/abc.txt
FileObject dir = manager.resolveFile("sftp://user:pass@localhost:" + port +
"/dir", options);
for (FileObject child : dir.getChildren()) {
if (UriParser.decode(child.getName().getBaseName()).equals("a*.txt")) {
child.delete();
}
}
// expected: only a*.txt is deleted; actual: abc.txt is deleted as well
{code}
Real-world impact: Kestra's {{plugin-fs}} (VFS 2.10.0, mwiede JSch 2.28.7)
loses data with its SFTP {{Delete}} task. With {{regExp}} matching only
{{a*.csv}}, {{abc.csv}} is deleted too. With an explicit path to the missing
file {{del?.csv}}, the existing {{delA.csv}} is deleted.
Suggested fix (PR to follow): escape backslash, {{*}} and {{?}} with a
backslash in the paths passed to the {{ChannelSftp}} methods that expand
wildcards. Leave {{mkdir}} unescaped, because it does not unquote. Also encode
{{?}} when resolving listed children.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)