Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Net::IMAP connection uses insecure deprecated options #1586

Open
nevans opened this issue Sep 19, 2023 · 7 comments · May be fixed by #1587
Open

Net::IMAP connection uses insecure deprecated options #1586

nevans opened this issue Sep 19, 2023 · 7 comments · May be fixed by #1587

Comments

@nevans
Copy link
Contributor

nevans commented Sep 19, 2023

The parameters that are used to create the Net::IMAP connection in Mail::IMAP are undocumented:

imap = Net::IMAP.new(settings[:address], settings[:port], settings[:enable_ssl], nil, false)

I believe the documentation was removed in 2007 (ruby/net-imap@e631911e). Pending the following PR: ruby/net-imap#175, the next release of net-imap will print a deprecation warning when those parameters are used. About a year later, they'll be removed entirely.

A bigger issue is that the fifth and final argument is false: that is the verify parameter and by setting it to false, the SSLContext will have verify_mode: OpenSSL::SSL::VERIFY_NONE.

Proposal

When Hash.try_convert(enable_ssl) returns a Hash, that will be used with

  Net::IMAP.new(settings[:address],
                port: settings[:port],
                ssl: Hash.try_convert(settings[:enable_ssl]))

When Hash.try_convert(enable_starttls) returns a Hash, that will be used with

  imap.starttls Hash.try_convert(settings[:enable_starttls])

In this way, any SSLContext attribute can be set.

When enable_ssl or enable_starttls are truthy but not hash-like, use {}. This way, the default is secure.

I can write a PR for this, if you agree with my proposal.

@nevans
Copy link
Contributor Author

nevans commented Sep 19, 2023

I haven't tested this yet, but it's tentatively as simple as the following:

        ssl      = settings[:enable_ssl]
        starttls = settings[:enable_starttls]
        ssl      &&= Hash.try_convert(ssl)      || {}
        starttls &&= Hash.try_convert(starttls) || {}

        imap = Net::IMAP.new(settings[:address], port: settings[:port], ssl: ssl)

        imap.starttls(starttls) if starttls

nevans added a commit to nevans/mail that referenced this issue Sep 20, 2023
This fixes the insecure `verify = false` argument that was previously
unconfigurable.  Now _any_ SSLContext params can be set on the IMAP
connection.

The original parameters have been undocumented since ~2007, will print
deprecation warnings in the next release and will be removed in a year.

Fixes mikel#1586.
@nevans nevans linked a pull request Sep 20, 2023 that will close this issue
@Fjan
Copy link

Fjan commented Oct 9, 2023

Some mail servers use self-signed certificates. There is not much wrong with that because they mainly care about encryption (which self-signed provides), and care less about MITM (because that's pretty rare on server to server communication). So I would keep the default VERIFY_NONE. If we do decide to change it then make sure to update the major gem version number, because this will break stuff for some people.

@nevans
Copy link
Contributor Author

nevans commented Oct 10, 2023

This library is used in plenty of situations where the identity of the remote server cannot be safely assumed without verification.

Although I understand this will be considered a breaking change by some people, as far as I'm concerned this is shocking behavior. It's broken for everyone now, to put it mildly. Fixing security bugs this severe should not cause a major version bump for the simple reason that a major version bump will prevent users from receiving the security fix. Every bugfix changes behavior, by definition, and that always runs the risk of being backward incompatible for someone. The API is compatible and it should only affect servers or clients that have been misconfigured.

We might not have been surprised by this as the default in 2012 (unfortunately). But in 2023, there is frankly no excuse for a TLS client to not verify the server's identity by default. If users can't figure out how to set up Let's Encrypt or add a ca_file or ca_path to their SSLContext, then they should be forced to explicitly ask for VERIFY_NONE. This is how nearly every other piece of client software has worked for over a decade.

From RFC-3501 (2006):

During the [TLS] negotiation, the client MUST check its understanding of the server hostname against the server's identity as presented in the server Certificate message, in order to prevent man-in-the-middle attacks. If the match fails, the client SHOULD either ask for explicit user confirmation, or terminate the connection and indicate that the server's identity is suspect.

For the purposes of a library like this gem, requiring the user to add an explicit verify_mode: OpenSSL::SSL::VERIFY_NONE to their configuration would satisfy the "explicit user confirmation" requirement. And, fortunately, PR #1587 should make it relatively easy for users who want to do so. 🙂 (Although, why not set ca_file instead?)

@nevans
Copy link
Contributor Author

nevans commented Oct 10, 2023

Also, for what it's worth, net-imap v0.4.0 was released last week, and it does include ruby/net-imap#175. Please let me know if PR #1587 needs any changes. I could even make it slightly simpler to disable host verification, if that's deemed necessary. 😉

@Fjan
Copy link

Fjan commented Oct 10, 2023

I asked Google Bart about the he number of mail servers with a self-signed certificates, and after some prodding it came up with 7%, stating that most of those would be on internal corporate networks (where you can't easily get a certificate). No idea about the accuracy. Anyway, I'm fine with the PR as it stands, I'm sure the people who need it can find a way to disable verification again, but the mail gem maintainers are the ones to convince.

@nevans
Copy link
Contributor Author

nevans commented Oct 12, 2023

I'm sure the people who need it can find a way to disable verification again

I'm currently working on SASL-related PRs for both net-smtp and net-pop. And, although net-imap has deprecated this particular call signature (Net::IMAP.new(host, port, true, ca_certs, verify)) in favor of the ssl: ssl_context_params, I notice that net-smtp uses has tls_verify and tls_hostname keyword params, in addition to ssl_context_params.

So, if it's important, I think it's fine to add tls_verify: false as a shortcut for ssl_contect_params: {verify_mode: OpenSSL::SSL::VERIFY_PEER}.

@SteveRawlinson
Copy link

FYI the deprecation warning in Net::IMAP has appeared. I appreciate the discussion above regarding 'breaking changes', but if this issue isn't addressed one way or another reasonably shortly all use of IMAP by users of this library will break.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants