{"record":{"id":"93e7e4a3d7f5731f","repo":"mastra-ai/mastra","slug":"unsupported-encryption-algorithm-prefix","errorCode":null,"errorMessage":"Unsupported encryption algorithm: ${prefix}","messagePattern":"Unsupported encryption algorithm: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/slack/src/crypto.ts","lineNumber":86,"sourceCode":"\n  const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n  const authTag = cipher.getAuthTag();\n\n  return `${ALGO_PREFIX}:${salt.toString('base64')}:${iv.toString('base64')}:${authTag.toString('base64')}:${encrypted.toString('base64')}`;\n}\n\n/**\n * Decrypt data produced by encrypt().\n */\nexport function decrypt(ciphertext: string, key: string): string {\n  const colonIdx = ciphertext.indexOf(':');\n  if (colonIdx === -1) {\n    throw new Error('Invalid ciphertext format');\n  }\n\n  const prefix = ciphertext.slice(0, colonIdx);\n  if (prefix !== ALGO_PREFIX) {\n    throw new Error(`Unsupported encryption algorithm: ${prefix}`);\n  }\n\n  const payload = ciphertext.slice(colonIdx + 1);\n  const [saltB64, ivB64, authTagB64, encryptedB64] = payload.split(':');\n  if (!saltB64 || !ivB64 || !authTagB64 || encryptedB64 === undefined) {\n    throw new Error('Invalid ciphertext payload');\n  }\n\n  const salt = Buffer.from(saltB64, 'base64');\n  const derived = Buffer.from(hkdfSync('sha256', key, salt, 'mastra-slack-encryption', 32));\n  const iv = Buffer.from(ivB64, 'base64');\n  const authTag = Buffer.from(authTagB64, 'base64');\n  const encrypted = Buffer.from(encryptedB64, 'base64');\n\n  const decipher = createDecipheriv('aes-256-gcm', derived, iv);\n  decipher.setAuthTag(authTag);\n  return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8');\n}","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/channels/slack/src/crypto.ts#L68-L104","documentation":"decrypt() in channels/slack/src/crypto.ts parses ciphertext of the form 'prefix:salt:iv:authTag:encrypted'. The prefix before the first colon must equal ALGO_PREFIX (the algorithm tag this library encrypts with). A mismatched prefix means the data was not encrypted by this library's encrypt() or was produced by a different/older algorithm version.","triggerScenarios":"Calling #decryptPendingInstallation, #decryptInstallation, or #decryptConfigTokens with a stored value whose first colon-delimited segment differs from ALGO_PREFIX — e.g. plaintext stored in a field expected to be ciphertext, values encrypted by another tool, or ciphertext written by an older library version with a different algorithm prefix.","commonSituations":"Manually inserted or migrated rows in the storage backend; switching encryption keys/formats between versions; accidentally storing an unencrypted token where ciphertext is expected.","solutions":["Re-encrypt the value with the current library's encrypt() so the ciphertext carries the correct ALGO_PREFIX.","Delete/recreate the affected installation or config record so it is written fresh in the current format.","Verify the stored field actually contains ciphertext (should look like '<prefix>:base64:base64:base64:base64'), not a plaintext token."],"exampleFix":"// before (plaintext in storage)\nconst token = 'xoxb-123-456';\nawait store.save({ botToken: token });\n// after\nconst token = await crypto.encrypt('xoxb-123-456');\nawait store.save({ botToken: token });","handlingStrategy":"validation","validationCode":"function looksLikeCiphertext(v) {\n  if (typeof v !== 'string') return false;\n  const [prefix] = v.split(':');\n  return Boolean(prefix) && /^[A-Za-z0-9_-]+$/.test(prefix);\n}\nif (!looksLikeCiphertext(stored)) throw new Error('value is not library-encrypted ciphertext; re-encrypt it');","typeGuard":"function isCiphertext(v: unknown): v is string {\n  return typeof v === 'string' && v.includes(':') && /^[a-z0-9-]+:/i.test(v);\n}","tryCatchPattern":"try {\n  const token = await decrypt(stored);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unsupported encryption algorithm')) {\n    // value written by different format/version: re-encrypt or re-install\n    await reInstallSlackAgent(agentId);\n  } else throw err;\n}","preventionTips":["Only store values produced by the library's encrypt() in encrypted fields.","Tag stored ciphertext with a version so migrations are detectable.","Never paste plaintext tokens into storage columns meant for ciphertext."],"tags":["crypto","decryption","data-format"],"backgroundTag":"unsupported-encryption-algorithm","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}