scp fails with -T in different scp versions
In new enough versions of scp
from OpenSSH, this is what -T
does:
-T
Disable strict filename checking. By default when copying files from a remote host to a local directoryscp
checks that the received filenames match those requested on the command-line to prevent the remote end from sending unexpected or unwanted files. Because of differences in how various operating systems and shells interpret filename wildcards, these checks may cause wanted files to be rejected. This option disables these checks at the expense of fully trusting that the server will not send unexpected filenames.
Some insight:
When you scp
to or from a remote location, your local scp
(the client) runs ssh
under the hood to connect to the remote location and run a specific command there. The command is passed as a single string and interpreted by the remote user's shell, like any command passed via ssh
.
In case of scp
the command is… scp
; with special options though. The options are undocumented (you won't find them in man 1 scp
), they turn scp
into a server.
A shell is involved on the remote side. In general the shell can interpret wildcards and the local scp
cannot really tell what the result will be. If you know what you're doing, you may find -T
useful when using wildcards (like *
).
Your scp
s 7.2 seem too old to support -T
, the option was added in the version 8.0. The more important thing is only then the whole strict filename checking was added.
OpenSSH 8.0 was released on 2019-04-17.
[…]
This release contains mitigation for a weakness in the
scp(1)
tool and protocol (CVE-2019-6111): when copying files from a remote system to a local directory,scp(1)
did not verify that the filenames that the server sent matched those requested by the client. This could allow a hostile server to create or clobber unexpected local files with attacker-controlled content.This release adds client-side checking that the filenames sent from the server match the command-line request,
The scp protocol is outdated, inflexible and not readily fixed. We recommend the use of more modern protocols like sftp and rsync for file transfer instead.
[…]
scp(1)
: Relating to the above changes toscp(1)
; the scp protocol relies on the remote shell for wildcard expansion, so there is no infallible way for the client's wildcard matching to perfectly reflect the server's. If there is a difference between client and server wildcard expansion, the client may refuse files from the server. For this reason, we have provided a new-T
flag toscp
that disables these client-side checks at the risk of reintroducing the attack described above.
(source)
This means your oldish scp
s that don't support -T
behave by default like newer scp
with -T
. Therefore if you really want -T
then the lack of support for it is not a problem. It can be a problem if you want newer scp
without -T
, i.e. if you want strict filename checking (not implemented in older scp
s).
Do you want it or not? Well, check the (already mentioned) CVE-2019-6111:
An issue was discovered in OpenSSH 7.9. Due to the scp implementation being derived from 1983 rcp, the server chooses which files/directories are sent to the client. However, the scp client only performs cursory validation of the object name returned (only directory traversal attacks are prevented). A malicious scp server (or Man-in-The-Middle attacker) can overwrite arbitrary files in the scp client target directory. If recursive operation (
-r
) is performed, the server can manipulate subdirectories as well (for example, to overwrite the.ssh/authorized_keys
file).
If your scp
s were new enough, they would by default perform strict filename checking to protect you from malicious servers. But if you used a wildcard then they might reject files you really want. In such case, if you trusted the server, you could use -T
to disable strict filename checking. The conclusion is: with new scp
you want the default behavior (no -T
), unless you know you need -T
and accept the risk.
With old scp
you don't have a choice (other than upgrading), there is no strict filename checking in the first place.
Note you did not use any wildcards to be expanded by the remote shell, so if your scp
s were new, then the usage of -T
would only lower the security. The idea to use -T
in this case is potentially harmful and gives nothing good in exchange.
With old scp
s their lack of strict filename checking is like -T
for new scp
. By simply using your old scp
s (without -T
obviously) you can achieve what you recklessly wanted (-T
); but in my opinion you shouldn't have wanted this.
It's a mystery to me why only one of your two scp
s complained about -T
. It doesn't matter. If you trust the server then use your old or newer scp
s without -T
; if you don't really trust the server then upgrade and use new scp
s without -T
.
Or better don't use scp
at all. Note the (already cited) statement:
The scp protocol is outdated, inflexible and not readily fixed. We recommend the use of more modern protocols like sftp and rsync for file transfer instead.
I agree. IMO scp
is a quick and dirty hack that stuck. That's why you need to quote some filenames twice: for the local and the remote shell. And if you know how (or worse: if you don't have a clue) then you can even inject code. E.g. this command:
scp 'router:nonexistent; beep' whatever
makes my router beep! You can only inject code you are able to run via ssh
anyway, but if running code is not your intention (and I guess with scp
it never is) and you don't know how to quote for scp
then you may run something you don't want.