4

Background

I've inherited a legacy build system based on Webpack 4 and run through yarn, which is run both on local development environments and in the cloud. Recently, Microsoft began to roll out a breaking change whereby the build agents allocated to the pipeline that runs this build system are now sometimes provisioned with Node 18 instead of Node 16.

I've come to learn that a breaking change in Node 18 is that it ships with a new OpenSSL provider, which has dropped support for the old md4 cryptographic hashing algorithm that is used internally by Webpack 4.

For backwards compatability, Node 18 has added a new NODE_OPTIONS command line flag, --openssl-legacy-provider, which can be used to force it to use a legacy OpenSSL provider that still supports the md4 algorithm. More recent versions of Node 16 have also back-ported support for this option, but only in the case that a newer version of the OpenSSL provider is being used than the one that ships with Node 16.

The Problem

Currently, we have two versions of the build system. The current one, which runs on Node 16 just fine, and a modified one that runs on Node 18 using the --openssl-legacy-provider flag but fails to run on Node 16 because the option is not allowed.

Ideally, I would like to get the build system into a state where it can run on either Node 16 or Node 18. I believe the key to this is to get both versions of Node to use the same legacy OpenSSL provider.

Potential Solutions

Our current interim solution has been to update our pipelines to force build agents to always use Node 16. Clearly this isn't a good long-term solution, though.

The only reason Node 18 is breaking for us is that Webpack is using the md4 algorithm. It is possible to configure output.hashFunction in Webpack's configuration, to tell it to use another algorithm like sha256, but there are also hard-coded uses of md4 in Webpack 4 that can't be configured so this configuration option hasn't solved the issue for us.

I've tried updating this legacy build system to Webpack 5, which has a built-in xxhash64 hashing algorithm that doesn't rely on OpenSSL and so should be able to work on either version of Node. But unfortunately we rely on several third party plugins that haven't been updated for years, and don't have successors that support Webpack 5. So while of course it would be possible to update it, it's probably going to be a lot more work than any other solution, and as I mentioned this is a legacy build system.

Another potential solution that we could do, but would prefer not to do, would be to restrict our build agents to all run with a version of Node >= 18, and also update all our local development environments to use Node 18. I'd prefer to treat this option as a last resort.

I've also seen references to creating a file called openssl.cnf and setting an OPENSSL_CONF environment variable to the path to that file, as a way to tell any version of node to use the same OpenSSL provider. But I haven't been to find any instructions on how to configure an environment variable in local development environments. I'm familiar with using the dotenv library to access environment variables specified in a .env file through process.env, for example, but as this solution doesn't require me to access these variables through code it doesn't feel applicable here.

I've also looked for ways to query the version of Node when running a yarn script, in order to determine whether or not it's safe to use the --openssl-legacy-provider option, but haven't found any information about how to do this. If it's even possible at all.

tl;dr

What I'm looking to achieve is a way to run a yarn script using the legacy OpenSSL provider without knowing ahead of time if it will be running on Node 16 or Node 18.

Mark Hanna
  • 3,206
  • 1
  • 17
  • 25
  • Any luck now I’m excatly looking for same – super cool Apr 12 '23 at 14:36
  • 1
    Unfortunately not, sorry. The potential solution I found that sounded most promising was to set up a config file for OpenSSL that tells it to use the legacy provider in a way that both Node versions understand, but I wasn't able to get that working. Here's a link to where I found info like that, if you're able to get it working please come back to say so: https://stackoverflow.com/a/69476335/1710523 – Mark Hanna Apr 12 '23 at 21:23

0 Answers0