Skip to content

ftp: reject control bytes in ACCT and alternative-to-user - #22301

Closed
alhudz wants to merge 1 commit into
curl:masterfrom
alhudz:ftp-acct-alt-crlf
Closed

ftp: reject control bytes in ACCT and alternative-to-user#22301
alhudz wants to merge 1 commit into
curl:masterfrom
alhudz:ftp-acct-alt-crlf

Conversation

@alhudz

@alhudz alhudz commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

ftp_state_user_resp() writes CURLOPT_FTP_ACCOUNT into an ACCT command and CURLOPT_FTP_ALTERNATIVE_TO_USER as a replacement for the USER line, both straight through Curl_pp_sendf() with no control-byte check. Once a server answers USER with 332, an account of one\r\nDELE f goes out as ACCT one followed by a separate DELE f line; the alternative-to-user string smuggles a command the same way when the server rejects USER. Tests 2115 and 2116 drive both paths and show the injected DELE reaching the server on the current code.

The URL path and the USER/PASS credentials already reject control octets (REJECT_CTRL / str_has_ctrl); these two option-sourced command fields were the gap. Reject a byte below 0x20 in both values in ftp_state_user_resp() before the command line is assembled, so the guard sits where the command is built rather than in each option setter.

A CR or LF in the CURLOPT_FTP_ACCOUNT or CURLOPT_FTP_ALTERNATIVE_TO_USER string split the control-channel command line and smuggled a second FTP command. Reject a byte below 0x20 in both values before the command is built.
@github-actions github-actions Bot added the tests label Jul 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR closes an FTP command-injection gap by rejecting control bytes (e.g., CR/LF) in two option-sourced strings that are incorporated into FTP control commands in ftp_state_user_resp().

Changes:

  • Add a small helper to detect control bytes in strings used in FTP control commands and apply it to CURLOPT_FTP_ACCOUNT (ACCT) and CURLOPT_FTP_ALTERNATIVE_TO_USER.
  • Return CURLE_BAD_FUNCTION_ARGUMENT with an explanatory error when either value contains a control byte.
  • Add new tests to ensure embedded CRLF in these option values is rejected and does not reach the server.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
lib/ftp.c Reject control bytes in ftp-account and ftp-alternative-to-user values before assembling/sending FTP control commands.
tests/data/test2115 New regression test ensuring CRLF injection via ftp-account is rejected and the injected command is not sent.
tests/data/test2116 New regression test ensuring CRLF injection via ftp-alternative-to-user is rejected and the injected command is not sent.
tests/data/Makefile.am Register new tests 2115 and 2116 in the test data makefile list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@bagder bagder added the FTP label Jul 12, 2026
@bagder bagder closed this in 9494750 Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants