Using the Alokai CA store
Stop trusting a distrusted certificate authority without upgrading Node.js or rebuilding your image.
When a certificate authority (CA) is compromised, your application should stop trusting it right away. Node.js makes that hard: it doesn't read the operating system's trust store, but a copy of Mozilla's root store compiled into the node binary. Only a newer Node.js release can remove a root from that copy.
The Alokai CA store is a set of trusted root certificates that Alokai maintains and mounts into every application container. By setting two environment variables, your application trusts the Alokai CA store instead of the store compiled into Node.js. When a CA is distrusted, Alokai updates the store, and your application picks up the change on its next deploy, with no Node.js upgrade or image rebuild.
Why you might need it
In October 2026, the keys of eight eMudhra intermediate CAs were compromised. They chain to the emSign ECC Root CA - G3 root and were also cross-signed by Sectigo's AAA Certificate Services root. Node.js removed both roots in these releases:
| Node.js line | Fixed in |
|---|---|
| 22 | 22.23.4 |
| 24 | 24.22.1 |
| 26 | 26.12.1 |
Every older Node.js binary still trusts both roots, so it accepts certificates issued with the compromised keys.
Upgrading Node.js is the best fix. If you can't upgrade right away, for example because you run an older or end-of-life Node.js version, opt in to the Alokai CA store instead.
Opting in
The Alokai CA store is mounted read-only at /etc/ssl/alokai/ca-bundle.pem in the storefront container, the middleware container, and every additional application. Mounting it alone doesn't change anything: your application keeps using the store compiled into Node.js until you opt in.
Set the environment variables
Add both variables to each application that should use the Alokai CA store (the storefront, the middleware, or an additional application). You can set them in the Console under Environment variables, or through the Alokai Cloud API.
NODE_OPTIONS=--use-openssl-ca
SSL_CERT_FILE=/etc/ssl/alokai/ca-bundle.pem--use-openssl-ca makes Node.js use OpenSSL's trust store instead of its compiled-in one, and SSL_CERT_FILE points OpenSSL at the Alokai CA store.
Already setting NODE_OPTIONS?
Setting NODE_OPTIONS replaces its current value. If you already pass flags through it, append --use-openssl-ca to them, for example NODE_OPTIONS=--max-old-space-size=4096 --use-openssl-ca.
Redeploy
Saving the variables redeploys your instance. The new pods start with the opt-in and trust only the certificates in the Alokai CA store.
What's in the store
The Alokai CA store contains the publicly trusted root CAs, minus the roots involved in the eMudhra compromise:
| Root | Status | Why |
|---|---|---|
| emSign ECC Root CA - G3 | Removed | The compromised intermediates chain to it. |
| AAA Certificate Services (Sectigo) | Removed | It cross-signed all eight compromised keys. |
| emSign Root CA - G1 | Trusted | Not affected. eMudhra is moving its customers onto this root, so removing it would break legitimate sites. |
| emSign Root CA - C1, emSign ECC Root CA - C3 | Trusted | Not part of this compromise. |
Store updates
Alokai updates the store when a root CA is distrusted. The file in your container updates in place, but Node.js reads it only at startup. A running application keeps the store it loaded until its next deploy or restart.
Verifying the opt-in
Run these commands in a shell in your application container.
Check that the application process started with both variables. The command assumes the application runs as process 1, which holds when your image starts node directly:
tr '\0' '\n' </proc/1/environ | grep -E '^(NODE_OPTIONS|SSL_CERT_FILE)='Check that the store no longer contains the distrusted roots. The command should print distrusted roots: none:
node -e 'const{X509Certificate}=require("crypto");const pems=require("fs").readFileSync("/etc/ssl/alokai/ca-bundle.pem","utf8").match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);const bad=pems.map(p=>new X509Certificate(p).subject.match(/CN=(.*)/)?.[1]).filter(s=>/emSign ECC Root CA - G3|AAA Certificate Services/.test(s));console.log(pems.length+" certificates, distrusted roots: "+(bad.length?bad.join("; "):"none"))'Check that your Node.js binary honors SSL_CERT_FILE. Pointed at an empty file, it should trust nothing and print UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
NODE_OPTIONS=--use-openssl-ca SSL_CERT_FILE=/dev/null node -e 'fetch("https://api.github.com").then(()=>console.log("BAD: node ignores SSL_CERT_FILE"),e=>console.log(e.cause?.code))'If it prints BAD: node ignores SSL_CERT_FILE, your Node.js binary doesn't support the override. A network error such as ENOTFOUND or ECONNREFUSED means the container can't reach api.github.com, and the check proves nothing.
Don't check from inside your application
tls.rootCertificates and tls.getCACertificates('bundled') always list the store compiled into Node.js, whether you opted in or not. On an older Node.js version they still show emSign ECC Root CA - G3, even though it isn't trusted under the opt-in. Use the commands above instead.