Commit 09b8c8be0a4 for nodejs

commit 09b8c8be0a47a3a3a4e2d6ae11bcead55ef52c2b
Author: Filip Skokan <panva.ip@gmail.com>
Date:   Tue Sep 22 22:18:26 2026 +0200

    crypto: convert importKey data as a union

    Choose the BufferSource or JsonWebKey branch from the value, then
    check the requested format after algorithm normalization.

    Signed-off-by: Filip Skokan <panva.ip@gmail.com>
    Assisted-by: Codex
    PR-URL: https://github.com/nodejs/node/pull/66237
    Reviewed-By: James M Snell <jasnell@gmail.com>
    Reviewed-By: Aviv Keller <me@aviv.sh>

diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js
index 847017529dc..73ae08fa1e1 100644
--- a/lib/internal/crypto/webcrypto.js
+++ b/lib/internal/crypto/webcrypto.js
@@ -1,6 +1,7 @@
 'use strict';

 const {
+  ArrayBufferIsView,
   ArrayIsArray,
   ArrayPrototypeSlice,
   FunctionPrototypeCall,
@@ -39,6 +40,7 @@ const {
 const {
   codes: {
     ERR_ILLEGAL_CONSTRUCTOR,
+    ERR_INVALID_ARG_TYPE,
     ERR_INVALID_THIS,
   },
 } = require('internal/errors');
@@ -85,6 +87,7 @@ const {
 } = require('internal/crypto/random');

 const {
+  isArrayBuffer,
   isPromise,
 } = require('internal/util/types');

@@ -1114,7 +1117,8 @@ function importKeyImpl(
   const prefix = prepareSubtleMethod(this, 'importKey', arguments.length, 5);
   let i = 0;
   format = convertSubtleArgument(prefix, 'KeyFormat', format, i++);
-  const type = format === 'jwk' ? 'JsonWebKey' : 'BufferSource';
+  const type = ArrayBufferIsView(keyData) || isArrayBuffer(keyData) ?
+    'BufferSource' : 'JsonWebKey';
   keyData = convertSubtleArgument(prefix, type, keyData, i++);
   algorithm = convertSubtleArgument(
     prefix, 'AlgorithmIdentifier', algorithm, i++);
@@ -1124,6 +1128,11 @@ function importKeyImpl(

   const normalizedAlgorithm = normalizeAlgorithm(algorithm, 'importKey');

+  if ((format === 'jwk') !== (type === 'JsonWebKey')) {
+    throw new ERR_INVALID_ARG_TYPE(
+      'keyData', format === 'jwk' ? 'JsonWebKey' : 'BufferSource', keyData);
+  }
+
   return FunctionPrototypeCall(
     importKeySync,
     this,
diff --git a/test/parallel/test-webcrypto-import-union.js b/test/parallel/test-webcrypto-import-union.js
new file mode 100644
index 00000000000..3391ba5c8dc
--- /dev/null
+++ b/test/parallel/test-webcrypto-import-union.js
@@ -0,0 +1,35 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+  common.skip('missing crypto');
+
+const assert = require('assert');
+const { subtle } = globalThis.crypto;
+const jwk = { kty: 'oct', k: 'AAAAAAAAAAAAAAAAAAAAAA' };
+
+(async () => {
+  for (const data of [new ArrayBuffer(16), new Uint8Array(16),
+                      new DataView(new ArrayBuffer(16)), Buffer.alloc(16)]) {
+    await assert.rejects(subtle.importKey('jwk', data, 'AES-GCM', true, ['encrypt']),
+                         TypeError);
+    Object.assign(data, jwk);
+    await assert.rejects(subtle.importKey('jwk', data, 'AES-GCM', true, ['encrypt']),
+                         TypeError);
+    await assert.rejects(subtle.importKey('jwk', data, 'unknown', true, ['encrypt']),
+                         { name: 'NotSupportedError' });
+  }
+  await assert.rejects(subtle.importKey('raw', {}, 'unknown', true, ['encrypt']),
+                       { name: 'NotSupportedError' });
+  await assert.rejects(subtle.importKey('raw', {}, 'AES-GCM', true, ['encrypt']),
+                       TypeError);
+  for (const data of [null, new SharedArrayBuffer(16)]) {
+    await assert.rejects(subtle.importKey('jwk', data, 'AES-GCM', true, ['encrypt']),
+                         { name: 'DataError' });
+  }
+  assert.strictEqual((await subtle.importKey('jwk', jwk, 'AES-GCM', true,
+                                             ['encrypt'])).type, 'secret');
+  await assert.rejects(subtle.importKey('raw', {
+    get kty() { throw new Error('converted JWK'); },
+  }, 'unknown', true, ['encrypt']), { message: 'converted JWK' });
+})().then(common.mustCall());