{"record":{"id":"98a7f8472b082df9","repo":"hoppscotch/hoppscotch","slug":"unwrapkey-requires-all-arguments-format-wrappedk","errorCode":null,"errorMessage":"unwrapKey requires all arguments: format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages","messagePattern":"unwrapKey requires all arguments: format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/hoppscotch-js-sandbox/src/cage-modules/crypto.ts","lineNumber":963,"sourceCode":"        const unwrapAlgorithmRaw = ctx.vm.dump(args[3])\n        const unwrapAlgorithm = normalizeAlgorithm(unwrapAlgorithmRaw)\n        const unwrappedKeyAlgorithmRaw = ctx.vm.dump(args[4])\n        const unwrappedKeyAlgorithm = normalizeAlgorithm(\n          unwrappedKeyAlgorithmRaw\n        )\n        const extractable = ctx.vm.dump(args[5]) as boolean\n        const keyUsages = ctx.vm.dump(args[6]) as KeyUsage[]\n\n        if (\n          !format ||\n          !wrappedKeyHandle ||\n          !unwrappingKeyHandle ||\n          !unwrapAlgorithm ||\n          !unwrappedKeyAlgorithm ||\n          extractable === undefined ||\n          !keyUsages\n        ) {\n          throw new Error(\n            \"unwrapKey requires all arguments: format, wrappedKey, unwrappingKey, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages\"\n          )\n        }\n\n        const wrappedKey = vmArrayToUint8Array(ctx, wrappedKeyHandle)\n        const unwrappingKey = getKeyFromHandle(unwrappingKeyHandle)\n\n        const promiseHandle = ctx.scope.manage(\n          ctx.vm.newPromise((resolve, reject) => {\n            trackAsyncOperation(\n              subtleImpl.unwrapKey(\n                format,\n                wrappedKey as BufferSource,\n                unwrappingKey,\n                unwrapAlgorithm as AlgorithmIdentifier,\n                unwrappedKeyAlgorithm as AlgorithmIdentifier,\n                extractable,\n                keyUsages","sourceCodeStart":945,"sourceCodeEnd":981,"githubUrl":"https://github.com/hoppscotch/hoppscotch/blob/1acb8a3a7581e4db32ba0d529170c4669a2e1053/packages/hoppscotch-js-sandbox/src/cage-modules/crypto.ts#L945-L981","documentation":"Thrown by the sandbox's crypto.subtle.unwrapKey wrapper when any of its seven arguments is missing/falsy. unwrapKey has the longest signature in WebCrypto: format, wrappedKey (byte handle), unwrappingKey (CryptoKey handle), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable (=== undefined check), and keyUsages (truthiness, so [] rejected).","triggerScenarios":"Calling unwrapKey with fewer than seven args; omitting either of the two algorithm objects; passing empty keyUsages []; passing wrappedKey as a plain array instead of a VM byte handle; passing extractable positionally wrong.","commonSituations":"Decrypting a wrapped CEK in a Hoppscotch test and forgetting unwrappedKeyAlgorithm or extractable; mixing up the argument order of the two algorithms.","solutions":["Pass all seven args in order: format, wrappedKey bytes, unwrappingKey handle, unwrapAlgorithm, unwrappedKeyAlgorithm, extractable boolean, non-empty keyUsages.","Confirm the wrappedKey is passed as a Uint8Array/byte handle, not a base64 string.","Ensure the unwrapping key has 'unwrapKey' usage and matches unwrapAlgorithm.","Provide keyUsages valid for unwrappedKeyAlgorithm (e.g. ['encrypt','decrypt'] for AES-GCM)."],"exampleFix":"// before\ncrypto.subtle.unwrapKey('raw', wrapped, unwrapKey, {name:'AES-GCM',iv})\n// after\ncrypto.subtle.unwrapKey('raw', wrapped, unwrapKey, {name:'AES-GCM',iv}, {name:'AES-GCM',length:256}, true, ['encrypt','decrypt'])","handlingStrategy":"validation","validationCode":"function safeUnwrapKey(format, wrappedKey, unwrappingKey, unwrapAlgo, unwrappedAlgo, extractable, keyUsages) {\n  if (!['raw','pkcs8','spki','jwk'].includes(format)) throw new TypeError('unwrapKey: bad format')\n  if (!wrappedKey || !unwrappingKey) throw new TypeError('unwrapKey: missing key data/handle')\n  if (!unwrapAlgo?.name || !unwrappedAlgo?.name) throw new TypeError('unwrapKey: both algorithms need a name')\n  if (typeof extractable !== 'boolean') throw new TypeError('unwrapKey: extractable must be boolean')\n  if (!Array.isArray(keyUsages) || !keyUsages.length) throw new TypeError('unwrapKey: keyUsages must be non-empty')\n  return crypto.subtle.unwrapKey(format, wrappedKey, unwrappingKey, unwrapAlgo, unwrappedAlgo, extractable, keyUsages)\n}","typeGuard":"const isCryptoKeyHandle = (v): boolean => v && typeof v === 'object' && '__keyId' in v","tryCatchPattern":null,"preventionTips":["Remember all seven positional args - this is the longest WebCrypto signature.","Pass wrappedKey as bytes, not a base64 string.","Give keyUsages valid for unwrappedAlgo."],"tags":["crypto","webcrypto","argument-validation","sandbox"],"backgroundTag":null,"analyzedSha":"1acb8a3a7581e4db32ba0d529170c4669a2e1053","analyzedAt":"2026-08-12T11:34:52.648Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}