curl · Report #3973228
50: CMake `HTTP_ONLY` does not disable SSH backends — SCP and SFTP remain usable
How it was found
Summary
The CMake HTTP_ONLY=ON option is documented as "Disable all protocols except HTTP" (CMakeLists.txt:538), but the implementation (CMakeLists.txt:541-557) only sets CURL_DISABLE_* flags for non-SSH protocols. It does not disable CURL_USE_LIBSSH2 or CURL_USE_LIBSSH. Since CURL_USE_LIBSSH2 defaults to ON, a build on any system with libssh2 installed produces a binary that advertises and accepts SCP and SFTP.
Affected versions
CMake builds from curl 7.38.0 through 8.21.0, plus affected 8.22.0 prerelease/development versions, when an SSH backend is available.
Root cause
The HTTP_ONLY block disables DICT, FILE, FTP, GOPHER, IMAP, IPFS, LDAP, LDAPS, MQTT, POP3, RTSP, SMTP, TELNET, TFTP, and WebSockets — but not the SSH backends. When CMake finds libssh2, it sets USE_LIBSSH2, which causes lib/curl_setup.h:773-775 to define USE_SSH. This makes the SCP/SFTP handlers in lib/protocol.c:283-309 live, includes them in version output, and allows initial URLs using those schemes.
Impact
An application that trusts the documented HTTP_ONLY build restriction as its protocol boundary — without also setting CURLOPT_PROTOCOLS_STR at runtime — unknowingly exposes SCP and SFTP. In SSRF-adjacent scenarios where an attacker controls the initial URL and the host has reachable SSH credentials, this widens the attack surface beyond what the builder intended.
The runtime restriction (--proto '=http,https' / CURLOPT_PROTOCOLS_STR) remains effective. I consider this primarily a build-policy violation with Low security impact given the preconditions required for exploitation.
Reproduction steps
- Use an affected curl source release, starting with 7.38.0, on a system where CMake can discover libssh2 or libssh.
- Configure curl with CMake using
HTTP_ONLY=ONand leave the available SSH backend enabled. - Build the curl command-line tool and libcurl.
- Inspect the configuration summary,
curl --version, andcurl_version_info()protocol list. - Observe the vulnerable build result: SCP and SFTP are listed alongside HTTP and HTTPS despite the documented HTTP-only configuration.
- Invoke the resulting command-line tool with an initial
sftp://URL pointing to a closed local port or another harmless unreachable endpoint. - Record the curl result and verbose connection trace.
- Confirm that curl selects the SFTP handler and attempts a network connection, producing a connection error rather than
CURLE_UNSUPPORTED_PROTOCOL. - Repeat the test with an initial
scp://URL and confirm that SCP is also active. - Optionally start a disposable SSH/SFTP server with isolated credentials and verify that the supposedly HTTP-only build can complete an authenticated SFTP download or upload.
- As a runtime-policy control, invoke the same vulnerable binary with
--proto '=http,https', or setCURLOPT_PROTOCOLS_STRtohttp,https. - Confirm that the SFTP URL is rejected before any network connection is attempted.
- As a build control, configure a second build with
HTTP_ONLY=ONand explicitly disable bothCURL_USE_LIBSSH2andCURL_USE_LIBSSH. - Build the control and confirm that its protocol list contains only HTTP and HTTPS and that SCP/SFTP URLs return
CURLE_UNSUPPORTED_PROTOCOL. - Confirm a fix by making
HTTP_ONLYenforce the final protocol-set invariant, including disabling SSH backends or excluding their protocol handlers regardless of dependency discovery. - Repeat the original configuration with libssh2 or libssh installed and verify that SCP and SFTP are absent from build reporting and rejected at runtime.
Expected result
HTTP_ONLY=ON must produce a build whose available protocol set is limited to HTTP and HTTPS, regardless of which optional protocol libraries are installed.
Vulnerable result
The CMake option disables many individual protocols but leaves SSH backends enabled. If an SSH library is found, the resulting build retains fully functional SCP and SFTP handlers.
Suggested fix
Add CURL_USE_LIBSSH2=OFF and CURL_USE_LIBSSH=OFF to the HTTP_ONLY block in CMakeLists.txt, or — more robustly — have HTTP_ONLY enforce the final protocol-set invariant so the computed and runtime protocol lists contain only HTTP and HTTPS regardless of which backends are detected.
Impact
Summary:
f an application accepts attacker-influenced URLs and relies on the documented HTTP_ONLY build restriction, an attacker may make it initiate SCP or SFTP connections to otherwise reachable SSH services. Depending on credentials available to the process, this could enable internal network access or unauthorized file downloads and uploads outside the intended HTTP-only boundary. An explicit runtime protocol allowlist prevents exploitation.