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

Dependency Extraction Webpack Plugin fails on Node v17 #36471

Closed
steakpinball opened this issue Nov 14, 2021 · 10 comments · Fixed by #40503
Closed

Dependency Extraction Webpack Plugin fails on Node v17 #36471

steakpinball opened this issue Nov 14, 2021 · 10 comments · Fixed by #40503
Assignees
Labels
Good First Issue An issue that's suitable for someone looking to contribute for the first time Needs Dev Ready for, and needs developer efforts [Package] Dependency Extraction Webpack Plugin /packages/dependency-extraction-webpack-plugin [Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended
Projects

Comments

@steakpinball
Copy link

Description

Running wp-scripts build to build a block results in this error:

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:67:19)
    at createHash (node:crypto:130:10)
    at DependencyExtractionWebpackPlugin.addAssets (C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\@wordpress\dependency-extraction-webpack-plugin\lib\index.js:200:19)
    at C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\@wordpress\dependency-extraction-webpack-plugin\lib\index.js:129:18        
    at fn (C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\webpack\lib\Compilation.js:476:10)
    at Hook.eval [as callAsync] (eval at create (C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:38:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\tapable\lib\Hook.js:18:14)       
    at cont (C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\webpack\lib\Compilation.js:3052:34)
    at C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\webpack\lib\Compilation.js:3100:10
    at symbolIterator (C:\Users\FramePush\Projects\Website\websitedev\generic-grid-layouts\node_modules\neo-async\async.js:3485:9)

The culprit is trying to use md4 hash:

Node v17 upgrades OpenSSL to 3.0, which moved md4 hash to the legacy provider. i.e. md4 is disabled by default.

webpack solved their issue by proving an md4 implementation. See webpack/webpack#14532. But the fix here could be as simple as switching to one of the hashes in the default provider, like md5. See https://wiki.openssl.org/index.php/OpenSSL_3.0#Provider_implemented_digests What is the significance of using md4?

A workaround with security implications as discussed in the webpack issue is to export NODE_OPTIONS=--openssl-legacy-provider before invoking node

Step-by-step reproduction instructions

Install Node version 17
Invoke wp-scripts build on a block plugin

Screenshots, screen recording, code snippet

No response

Environment info

Node 17.1.0
@wordpress/scripts 19.1.0

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@gziolo gziolo added [Package] Dependency Extraction Webpack Plugin /packages/dependency-extraction-webpack-plugin [Type] Bug An existing feature does not function as intended labels Nov 15, 2021
@gziolo gziolo added this to To do in Core JS Nov 15, 2021
@gziolo
Copy link
Member

gziolo commented Feb 11, 2022

It looks like Webpack exposes its own hashing util:
https://webpack.js.org/api/compilation-object/#createhash

It's very likely that we could use it as follows:

diff --git a/packages/dependency-extraction-webpack-plugin/lib/index.js b/packages/dependency-extraction-webpack-plugin/lib/index.js
index 0d9fc04bd5..40da8b9a73 100644
--- a/packages/dependency-extraction-webpack-plugin/lib/index.js
+++ b/packages/dependency-extraction-webpack-plugin/lib/index.js
@@ -1,7 +1,6 @@
 /**
  * External dependencies
  */
-const { createHash } = require( 'crypto' );
 const path = require( 'path' );
 const webpack = require( 'webpack' );
 // In webpack 5 there is a `webpack.sources` field but for webpack 4 we have to fallback to the `webpack-sources` package.
@@ -219,7 +218,8 @@ class DependencyExtractionWebpackPlugin {
 					filename,
 					query,
 					basename: basename( filename ),
-					contentHash: createHash( 'md4' )
+					contentHash: compilation
+						.createHash( 'md4' )
 						.update( assetString )
 						.digest( 'hex' ),
 				}

At least this is what I read from webpack/webpack#14584 where webpack added their own md4 implementation in Wasm.

@gziolo gziolo added Needs Dev Ready for, and needs developer efforts Good First Issue An issue that's suitable for someone looking to contribute for the first time labels Feb 11, 2022
@bliebek
Copy link

bliebek commented Feb 18, 2022

I'm going to work on this one.

@karmatosed
Copy link
Member

That's awesome @bliebek - I just assigned this to you as you dive in. Excited to see what you create ✨

@gziolo gziolo added the [Status] In Progress Tracking issues with work in progress label Feb 19, 2022
@gziolo gziolo moved this from To do to In progress in Core JS Feb 19, 2022
@bliebek
Copy link

bliebek commented Feb 23, 2022

@gziolo what's the point of sticking to md4 here? Maybe the solution can be as simple as adding hashFunction as a plugin parameter and providing md5 as fallback:

index 0d9fc04bd5..a411b8a2fb 100644
--- a/packages/dependency-extraction-webpack-plugin/lib/index.js
+++ b/packages/dependency-extraction-webpack-plugin/lib/index.js
@@ -1,7 +1,6 @@
 /**
  * External dependencies
  */
-const { createHash } = require( 'crypto' );
 const path = require( 'path' );
 const webpack = require( 'webpack' );
 // In webpack 5 there is a `webpack.sources` field but for webpack 4 we have to fallback to the `webpack-sources` package.
@@ -30,6 +29,7 @@ class DependencyExtractionWebpackPlugin {
                                outputFormat: 'php',
                                outputFilename: null,
                                useDefaults: true,
+                               hashFunction: 'md5',
                        },
                        options
                );
@@ -145,6 +146,7 @@ class DependencyExtractionWebpackPlugin {
                        injectPolyfill,
                        outputFormat,
                        outputFilename,
+                       hashFunction,
                } = this.options;
 
@@ -219,7 +221,7 @@ class DependencyExtractionWebpackPlugin {
                                        filename,
                                        query,
                                        basename: basename( filename ),
-                                       contentHash: createHash( 'md4' )
+                                       contentHash: createHash( hashFunction )
                                                .update( assetString )
                                                .digest( 'hex' ),
                                }
@@ -238,7 +240,7 @@ class DependencyExtractionWebpackPlugin {
                                        filename,
                                        query,
                                        basename: basename( filename ),
-                                       contentHash: createHash( 'md4' )
+                                       contentHash: createHash( hashFunction )

@gziolo
Copy link
Member

gziolo commented Feb 23, 2022

@gziolo what's the point of sticking to md4 here? Maybe the solution can be as simple as adding hashFunction as a plugin parameter and providing md5 as fallback:

We still support Node v12 and webpack v4, if md5 works with both, then we can simply switch the algorithm. I don't think we need to expose it as an option.

@bliebek
Copy link

bliebek commented Feb 23, 2022

I think it's neither the matter of node nor webpack version, but it's determined by OpenSSL version installed, see:
https://nodejs.org/docs/latest-v12.x/api/crypto.html#crypto_crypto_createhash_algorithm_options
https://nodejs.org/dist/latest-v17.x/docs/api/crypto.html#cryptocreatehashalgorithm-options

The algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are 'sha256', 'sha512', etc. On recent releases of OpenSSL, openssl list -digest-algorithms (openssl list-message-digest-algorithms for older versions of OpenSSL) will display the available digest algorithms.

@gziolo
Copy link
Member

gziolo commented Feb 23, 2022

Feel free to open patch and we will take it from there 👍🏻

@cbratschi
Copy link

I ran into this issue after upgrading from Node 16.x to 18. OpenSSL was not updated. How can we solve this issue?

@cbratschi
Copy link

Workaround (for now):

export NODE_OPTIONS=--openssl-legacy-provider

@gziolo
Copy link
Member

gziolo commented Apr 21, 2022

Let's try a simple fix by changing the OpenSSL provider: #40503.

@gziolo gziolo moved this from In progress to Done in Core JS May 5, 2022
marcelgerber added a commit to owid/owid-grapher that referenced this issue Jun 6, 2023
Otherwise, `yarn buildWordpressPlugin` throws in Node 18, see
WordPress/gutenberg#36471
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Good First Issue An issue that's suitable for someone looking to contribute for the first time Needs Dev Ready for, and needs developer efforts [Package] Dependency Extraction Webpack Plugin /packages/dependency-extraction-webpack-plugin [Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended
Projects
No open projects
Core JS
  
Done
Development

Successfully merging a pull request may close this issue.

5 participants