Skip to content

fix(files_external): validate FTP and SFTP ports as TCP port numbers - #63936

Open
bahman026 wants to merge 2 commits into
nextcloud:masterfrom
bahman026:fix/noid/files-external-validate-port
Open

fix(files_external): validate FTP and SFTP ports as TCP port numbers#63936
bahman026 wants to merge 2 commits into
nextcloud:masterfrom
bahman026:fix/noid/files-external-validate-port

Conversation

@bahman026

@bahman026 bahman026 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #63161, addressing the review suggestion there to validate that the port is an integer within the valid TCP range.

Summary

#63161 made FTP::__construct() fall back to the default port unless the configured value is numeric, mirroring the SFTP guard from #58350:

$parsedPort = $parameters['port'] ?? null;
$this->port = is_numeric($parsedPort) ? (int)$parsedPort : 21;

That fixes the empty-string crash, but is_numeric() still accepts values that are not usable TCP ports, and the cast then silently turns them into something else:

configured port is_numeric() result comment
"21.5" 21 truncated, no longer the configured value
"1e3" 1000 exponential notation accepted
"0" 0 not a valid port
"-2121" -2121 not a valid port
"65536" 65536 above the maximum

The port field of an external storage holds whatever the administrator typed, so all of these are reachable through the UI. FTP and SFTP are the only backends that read ['port'].

Fix

Add OCA\Files_External\Lib\PortHelper::parsePort(), which returns the given fallback unless the value is an integer, or a digit-only string, within 1-65535:

$this->port = PortHelper::parsePort($parameters['port'] ?? null, self::DEFAULT_PORT);

Both backends use it, and the hardcoded 21 / 22 defaults are replaced with a DEFAULT_PORT class constant.

For SFTP the port can also be part of the host field (somehost:2222). That value now goes through the same validation, and remains the fallback when the port field itself is empty or invalid, so somehost:2222 with an empty port still connects to 2222.

Valid configurations are unaffected: an integer, or a numeric string such as "2121", resolves exactly as before.

Checklist

Follow-up to nextcloud#63161. The port field of an external storage holds whatever the
admin typed, so `is_numeric()` still let through values that are not usable TCP
ports: "21.5" and "1e3" were silently truncated by the int cast, and "0",
"-2121" or "65536" were passed on to the connection as-is.

Add PortHelper::parsePort(), which only accepts an integer or a digit-only
string within the valid TCP port range of 1-65535 and otherwise returns the
given fallback. Use it for both FTP and SFTP, including the port that SFTP
parses out of the host field, and replace the hardcoded default ports with
class constants.

Signed-off-by: bahman026 <bahman026@gmail.com>
@bahman026
bahman026 requested a review from a team as a code owner September 2, 2026 07:43
@bahman026
bahman026 requested review from CarlSchwan, come-nc, icewind1991 and leftybournes and removed request for a team September 2, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants