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)

Reply via email to