{"record":{"id":"3780686cde33acb2","repo":"dotnet/runtime","slug":"using-node-without-crypto-support-to-enable-curre","errorCode":null,"errorMessage":"Using node without crypto support. To enable current operation, either provide polyfill for 'globalThis.crypto.getRandomValues' or enable 'node:crypto' module.","messagePattern":"Using node without crypto support\\. To enable current operation, either provide polyfill for 'globalThis\\.crypto\\.getRandomValues' or enable 'node:crypto' module\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/Common/JavaScript/loader/polyfills.ts","lineNumber":53,"sourceCode":"        }\n    }\n    if (ENVIRONMENT_IS_NODE) {\n        if (!globalThis.crypto) {\n            globalThis.crypto = <any>{};\n        }\n        if (!globalThis.crypto.getRandomValues) {\n            let nodeCrypto: any = undefined;\n            try {\n                // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n                // @ts-ignore:\n                nodeCrypto = await import(/*! webpackIgnore: true */\"node:crypto\");\n            } catch (err: any) {\n                // Noop, error throwing polyfill provided bellow\n            }\n\n            if (!nodeCrypto) {\n                globalThis.crypto.getRandomValues = () => {\n                    throw new Error(\"Using node without crypto support. To enable current operation, either provide polyfill for 'globalThis.crypto.getRandomValues' or enable 'node:crypto' module.\");\n                };\n            } else if (nodeCrypto.webcrypto) {\n                globalThis.crypto = nodeCrypto.webcrypto;\n            } else if (nodeCrypto.randomBytes) {\n                const getRandomValues = (buffer: Uint8Array) => {\n                    if (buffer) {\n                        buffer.set(nodeCrypto.randomBytes(buffer.length));\n                    }\n                };\n                globalThis.crypto.getRandomValues = getRandomValues as any;\n            }\n        }\n        if (!globalThis.performance) {\n            // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n            // @ts-ignore:\n            globalThis.performance = (await import(/*! webpackIgnore: true */\"perf_hooks\")).performance;\n        }\n    }","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/Common/JavaScript/loader/polyfills.ts#L35-L71","documentation":"initPolyfillsEarly() under Node tries to import('node:crypto'). If that import fails (Node built without OpenSSL, a bundled runtime without the crypto module, or an opaque sandbox blocking dynamic import) it installs a stub for globalThis.crypto.getRandomValues that throws this message when called. The throw is deferred until something actually requests random bytes — typically integrity check, GUID, or TLS within the runtime.","triggerScenarios":"Running the WASM loader in a Node build that excluded the crypto module (e.g. custom NodeJS build, Electron with --disable-crypto). Sandboxed environments (Cloudflare Workers in Node-compat mode, certain bundlers) that block dynamic import of node:crypto. Node compiled with --without-ssl.","commonSituations":"Electron main process with a stripped Node. Bun/Deno emulating Node where node:crypto import is partial. A bundler (webpack) that statically resolves the dynamic import to nothing. Container image with a minimal Node that lacks openssl.","solutions":["Use a standard Node.js distribution that includes crypto (node:crypto is built-in).","Provide a polyfill: set globalThis.crypto.getRandomValues to a function that fills the buffer from a CSPRNG before bootstrapping the loader.","If using a bundler, mark node:crypto as external so the dynamic import resolves at runtime.","Disable integrity checks (loaderConfig.disableIntegrityCheck=true) if randomness is only consumed by SRI — but other runtime paths still need getRandomValues."],"exampleFix":"// before: node:crypto blocked, getRandomValues throws on first use\n\n// after: provide polyfill before createDotnetRuntime\nimport { webcrypto } from 'node:crypto';\nglobalThis.crypto = webcrypto as any;\nawait dotnet.create();","handlingStrategy":"validation","validationCode":"function hasCryptoRandom(): boolean {\n  return typeof (globalThis as any).crypto?.getRandomValues === 'function';\n}\nif (!hasCryptoRandom()) {\n  // install polyfill before bootstrapping\n}","typeGuard":"function hasWebCrypto(): boolean {\n  const c = (globalThis as any).crypto;\n  return !!c && typeof c.getRandomValues === 'function';\n}","tryCatchPattern":"try { await dotnet.create(); } catch (e) {\n  if (/crypto support/.test((e as Error).message)) {\n    const { webcrypto } = await import('node:crypto');\n    (globalThis as any).crypto = webcrypto;\n    await dotnet.create();\n  } else throw e;\n}","preventionTips":["Use a standard Node.js build with OpenSSL included.","If running under a bundler, mark node:crypto as external.","Polyfill globalThis.crypto.getRandomValues before createDotnetRuntime in custom hosts.","Pin the Node version in CI/Dockerfile to one known to ship crypto."],"tags":["node","crypto","polyfill","environment"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}