The standard package manager for Node.js applications, npm, is changing. New npm installation policies may affect how you obtain and install some Node.js components.
What is happening, how does it affect MQ, and what will you need to do.
The new policy
From npm v12, the npm install command will not automatically execute scripts that are configured in a component’s package.json file. This is an effort to reduce the potential for malware creeping into your environment, and improve supply-chain integrity. A number of recent security vulnerabilities in the Node.js ecosystem have come from running infected scripts. As well as the announcement (linked above) there is additional related commentary here.
To help people plan for this change, npm v11.16 (which is already available) prints warnings about what will be blocked in the next major release.
While not identical, something similar is happening with the homebrewtool primarily used on MacOS: installation of packages (including the MQ Developer Toolkit) outside brew’s direct control now requires explicit trust.
How does this affect MQ
The ibmmq Node.js packages uses scripts in two ways during installation:
- A postinstall script downloads the MQ Redistributable Client packages for Windows and Linux x64. For other platforms, it simply tells you that you must obtain and install the MQ C client libraries by some other route.
- A build script (binding.gyp) compiles the C++ code needed to bridge between the Node.js environment and the MQ C libraries. There are some platforms which include this C++ native addon prebuilt; the build step is not then needed.
These two aspects are related, but are not direct dependencies in either direction. The MQ C Client libraries must be installed before your application can run. But they are not actually required during the build stage.
The intention of these scripts is to simplify and speed up the installation process wherever possible. And therefore making the whole experience of developing Node.js apps that use MQ as pain-free as we can.
The ibmmq package has a small number of nested or transitive dependencies, none of which require additional trust. These do not have scripts that need to be run during installation, so you will not see any new block in the ibmmq package.json file itself.
The warnings
If I run an installation with npm 11.16, I get this output:
npm warn allow-scripts 1 package has install scripts not yet covered by allowScripts:
npm warn allow-scripts ibmmq@2.1.9 (install: node-gyp-build; postinstall: node postinstall.mjs)
npm warn allow-scripts
npm warn allow-scripts Run `npm approve-scripts --allow-scripts-pending` to review, or `npm approve-scripts <pkg>` to allow.
These are the warnings that you need to decide what to do. It shows the two kinds of scripts that will be executed.
Different platform behaviour
On Windows and Linux x64, we automatically install the MQ client libraries as well as providing the prebuilt bridge layer. AIX and MacOS do not have a redistributable MQ Client package, but the bridge is still given to you prebuilt.
Whereas on Linux PPC and Linux s390x neither aspect is available: the bridge must be built on your local system, and you have to manually install the MQ client before running an application.
So the effects of blocking the ibmmq scripts will vary by platform.
One further aspect of npm install is worth mentioning. By default, any output from these scripts is hidden. To see the progress – or even just the warning that you must install the MQ C client – you have to look in the installation log files. Typically these will be under $HOME/.npm/logs. Using npm install --foreground-scripts ... makes the output more obvious.
What should I do?
The simplest solution, and one which is available from npm v11.16, is to make the ibmmq library “trusted”.
Run npm --approve-scripts ibmmq and a new block is added to your application’s package.json file. This will revert to the existing behaviour of installing the Redist Client package (where possible) and building the C++ bridge layer (where required).
This example show the new block.
{
"name": "amqsput",
"version": "0.0.1",
"description": "For demonstrating installation of MQ API",
"main": "amqsput.js",
"dependencies": {
"ibmmq": "2.1.9"
},
"allowScripts": {
"ibmmq@2.1.9": true
}
}
Note that the allowScriptsblock automatically inherits the same specific version (by default) as the actual dependency. Though there are options to not pin the version.
Without trusting the package
If you do not set the ibmmqpackage to trusted, and take no further steps, then there will be failures when you try to run an application. It appears that failure to run the scripts does NOT actually result in an installation failure; you cannot rely on the return code from npm install to know that some steps have been skipped.
The runtime failures will depend on the platform.
For example, on Linux x64, the application will not be able to locate the MQ C libraries:
$ node amqsput.js
Cannot find MQ C library.
System appears to be: linux[x64]
Has the MQ C client been installed?
Have you run setmqenv?
/home/metaylor/npmtest/node_modules/ibmmq/lib/mqi.js:287
throw err;
^
{
message: '/opt/mqm/lib/libmqm_r.so: cannot open shared object file: No such file or directory'
}
On Linux s390x, and other platforms without a prebuilt native addon, you will instead see something like:
$ node amqsput.js
/home/metaylor/npmtest/node_modules/node-gyp-build/node-gyp-build.js:60
throw new Error('No native build was found for ' + target + '\n loaded from: ' + dir + '\n')
Error: No native build was found for platform=linux arch=s390x runtime=node abi=127 uv=1 libc=glibc node=22.23.0
loaded from: /home/metaylor/npmtest/node_modules/ibmmq
at load.resolve.load.path (/home/metaylor/npmtest/node_modules/node-gyp-build/node-gyp-build.js:60:9)
at load (/home/metaylor/npmtest/node_modules/node-gyp-build/node-gyp-build.js:22:30)
...
Manually running denied steps
The simplest thing is to approve the ibmmq scripts. But if you prefer not to, then you can deal with it manually.
The postinstall script
This is only effective on Windows and Linux x64 anyway. You can either explicitly install the MQ C client libraries or execute the postinstall script directly:
$ cd ./node_modules/ibmmq
$ node postinstall.mjs
The addon build script
For platforms where there is no prebuilt version of the C++ addon module, you can force the build to happen. This step does not require the C client libraries to be available, but you will need them for application runtime.
$ cd ./node_modules/ibmmq
$ npm run install node-gyp-build
Summary
Improving the verification of your supply-chain, and making sure that subverted packages do not have the opportunity to spread is essential. The npm organisation has chosen the management of scripts as one of the features that is now needed.