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

fix: Improve heuristic for --openssl-legacy-provider (#19320) #19522

Merged
merged 2 commits into from
Jan 6, 2022

Conversation

eagleflo
Copy link
Contributor

@eagleflo eagleflo commented Jan 3, 2022

User facing changelog

  • Improved the heuristic for detecting whether --openssl-legacy-provider is needed

Additional details

Node 17+ can still be built against OpenSSL version 1 with --shared-openssl build parameter. In this case the option --openssl-legacy-provider does not work (and is not needed). We cannot assume that all versions of Node 17 are built with OpenSSL 3.

How has the user experience changed?

Native Node v17 as built by Arch Linux and Homebrew now works with Cypress again (after being broken in 9.1.1).

PR Tasks

  • [na] Have tests been added/updated?
  • Has the original issue (or this PR, if no issue exists) been tagged with a release in ZenHub? (user-facing changes only)
  • Has a PR for user-facing changes been opened in cypress-documentation?
  • [na] Have API changes been updated in the type definitions?
  • [na] Have new configuration options been added to the cypress.schema.json?

@eagleflo eagleflo requested a review from a team as a code owner January 3, 2022 17:59
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Jan 3, 2022

Thanks for taking the time to open a PR!

@eagleflo eagleflo requested review from jennifer-shehane and removed request for a team January 3, 2022 17:59
@CLAassistant
Copy link

CLAassistant commented Jan 3, 2022

CLA assistant check
All committers have signed the CLA.

@jennifer-shehane jennifer-shehane removed their request for review January 3, 2022 18:44
@emilyrohrbough emilyrohrbough self-requested a review January 4, 2022 19:13
// unconditionally, but it doesn't exist if Node was built against OpenSSL
// version 1.x.
if (semver.satisfies(config.resolvedNodeVersion, '>=17.0.0') &&
!process.versions.openssl.startsWith("1")) {
Copy link
Member

Choose a reason for hiding this comment

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

Given this issue is caused by Cypress's usage of wepback 4 + Node 17, the "best" solution for this issue would be to upgrade to webpack 5. I am looking into that work, however, for a (hopefully temporary) go-forward I think you change is on the right track since webpack uses the md4 cyrpto algorithm internally.

I am wonder if we need to make this solution a bit more robust though. The original change here assumed default the OpenSSL Library provided in Node 17 to be the OpenSSL 3.0.0 which introduced the --openssl-legacy-provider flag. Your change is assuming assuming Node 17 + OpenSSL 1.x.

In your summary / linked issues to Cloudflare, you noted that Node can be built with the --shared-openssl build parameter. This lead me to look further into Node's build options & theirbuild documentation. It looks like the OpenSSL library / configuration( & the cyrpto library) could be pretty open-ended if someone wanted to build node with custom paths.

Would it be possible for users to use a custom OpenSSL library that doesn't accept the --openssl-legacy-provider flag? Would that cause process.versions.openssl to be undefined?

Copy link
Member

Choose a reason for hiding this comment

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

Also, can we update the existing tests to add a validation check for this?

Copy link
Contributor Author

@eagleflo eagleflo Jan 4, 2022

Choose a reason for hiding this comment

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

Your change is assuming assuming Node 17 + OpenSSL 1.x.

My change does not assume Node 17 + OpenSSL 1.x, it just checks for that possibility and skips adding the option if that happens to be the case. The option is still applied on Node 17 + OpenSSL 3.x.


I fully agree that the best course of action for Cypress would be to upgrade to Webpack 5.61+. It's the right thing to do regardless from project health viewpoint. This whole workaround could then be removed.

Regarding uncertainty about building Node with custom versions of OpenSSL, Node.js core team says building against any shared libraries is effectively unsupported. I wouldn't support anything beyond OpenSSL 1.x and OpenSSL 3.x for this hopefully temporary fix.

If you wanted to make this more robust, I'd require crypto and check whether crypto.constants.OPENSSL_VERSION_NUMBER > 0x30000000. But that's essentially a more complicated way of testing the same thing.

Regarding cases where process.versions.openssl would be undefined, in theory it's possible to build Node.js without SSL at all. (This is obviously unsupported by most of the ecosystem and no major distro ships Node.js built like this.) Via this issue we've established that Cypress transitively relies on crypto being available; if you wanted to check for that, I'd do it much earlier.

Copy link
Member

Choose a reason for hiding this comment

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

My change does not assume Node 17 + OpenSSL 1.x, it just checks for that possibility and skips adding the option if that happens to be the case.

To me it seems like it might be safer to check for the possibility of OpenSSL 3.x and add it if its there. @mjhenkes thoughts?

Copy link
Contributor Author

@eagleflo eagleflo Jan 6, 2022

Choose a reason for hiding this comment

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

This option will be needed with future versions of OpenSSL until you upgrade Webpack. If OpenSSL were to increase their major version again checking explicitly for OpenSSL 3 would break.

Copy link
Member

Choose a reason for hiding this comment

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

True, but there's no guarantee the next MVB of OpenSSL will support the Legacy Provider and it's corresponding --openssl-legacy-provider flag either. 🤷🏻‍♀️ This is good conversation btw. I appreciate your responsiveness.

Copy link
Contributor Author

@eagleflo eagleflo Jan 6, 2022

Choose a reason for hiding this comment

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

I appreciate you making sure it's the appropriate fix.

We know for sure that the --openssl-legacy-provider option is not there with OpenSSL version 1.x. I also want to emphasize that we are now fixing existing breakage -- something many people have now encountered in the wild, even based on reports from the very small subset of users that engage with the project via GitHub.

We have no idea when or if OpenSSL 4 will be released -- and by the time OpenSSL 4 might be released, I really truly hope Cypress has long since moved on from webpack@4 and removed this workaround altogether!


Regarding support for the legacy provider, they just added it in OpenSSL 3 to draw a clear line between believed-safe and known-broken algorithms and ciphers. They had the opportunity to completely throw these algorithms away here, but they chose to keep supporting them to let their clients decide when and how to upgrade. They wisely mitigated the risk by not loading this provider by default and having their clients explicitly opt-in to it.

I would not expect this legacy provider to disappear anytime soon, as otherwise the currently clear upgrade path from OpenSSL 1.x (which is quite literally everywhere, for years to come) would suffer. This is of vital importance to the OpenSSL team since there still are multiple CVEs found in OpenSSL every year -- they need to keep providing as smooth upgrade experience as possible.

(I suspect that's also the reason why many rolling release distros have chosen to build Node.js with --shared-openssl in the first place -- they believe they will be better off updating OpenSSL systemwide rather than relying on the Node.js team for a new build. Unfortunately these very infrequent big OpenSSL upgrades then take more time to roll out since you have to fix and rebuild large parts of the whole distro. Arch Linux is looking to upgrade at the beginning of this year.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose one other way of solving this would be to copy the approach I took in fixing wrangler by spawning node --help and grepping for --openssl-legacy-provider. It's going to be slower and much harder to test, but maybe slightly more robust.

I have no insight into your plans and schedule wrt. webpack 5 adoption, so if this workaround is going to stay here for a longer while it might be wiser to take that approach. Who knows how long Node.js will keep that option around.

Copy link
Member

Choose a reason for hiding this comment

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

We can go head with what is here -- a new node process would be overkill. Based on your response, we know for sure --openssl-legacy-provider option is not supported with OpenSSL version 1.x and could potentially be supported in OpenSSL >3.x. Like you said v4 likely won't come quickly and we should be (fingers crossed) on a newer version of webpack by the time this would happen.

@eagleflo eagleflo force-pushed the issue-19320 branch 3 times, most recently from 16cb477 to 02db9c7 Compare January 4, 2022 22:57
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 this pull request may close these issues.

Cypress 9.1.1 + Node 17.2 (Win 11) Crashes
4 participants