{"record":{"id":"0cd1f7131a282bd0","repo":"gchq/CyberChef","slug":"invalid-secret-the-input-must-be-a-valid-base32-s","errorCode":null,"errorMessage":"Invalid secret. The input must be a valid base32 string (characters A–Z and 2–7).","messagePattern":"Invalid secret\\. The input must be a valid base32 string \\(characters A–Z and 2–7\\)\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/GenerateHOTP.mjs","lineNumber":64,"sourceCode":"                \"min\": 0,\n                \"integer\": true\n            }\n        ];\n    }\n\n    /**\n     *\n     */\n    run(input, args) {\n        const secretStr = new TextDecoder(\"utf-8\").decode(input).trim();\n\n        let secret;\n        try {\n            secret = secretStr ?\n                OTPAuth.Secret.fromBase32(secretStr.toUpperCase().replace(/\\s+/g, \"\")) :\n                new OTPAuth.Secret();\n        } catch {\n            throw new OperationError(\"Invalid secret. The input must be a valid base32 string (characters A–Z and 2–7).\");\n        }\n\n        const hotp = new OTPAuth.HOTP({\n            issuer: \"\",\n            label: args[0],\n            algorithm: \"SHA1\",\n            digits: args[1],\n            counter: args[2],\n            secret\n        });\n\n        const uri = hotp.toString();\n        const code = hotp.generate();\n\n        return `URI: ${uri}\\n\\nPassword: ${code}`;\n    }\n}\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/GenerateHOTP.mjs#L46-L82","documentation":"Thrown by GenerateHOTP when the user-supplied secret cannot be parsed as a valid RFC 4648 base32 string. CyberChef decodes the input as UTF-8, trims it, uppercases it, and strips whitespace before handing it to OTPAuth.Secret.fromBase32(). If that call rejects the value (illegal characters, wrong padding, empty-after-trim edge cases), the catch block surfaces this generic OperationError. It is an expected user-input error, not an internal fault.","triggerScenarios":"Calling GenerateHOTP.run() with input containing characters outside A-Z and 2-7 (e.g. '0', '1', '8', '9', lowercase before uppercasing if non-ASCII present), or with malformed padding. An empty string does NOT trigger it — an empty secret produces a new random OTPAuth.Secret() instead.","commonSituations":"Pasting a TOTP/HOTP secret that includes spaces or dashes that survive the whitespace strip, copying a hex-encoded or base64 secret by mistake, or feeding a secret with '=' padding the library rejects.","solutions":["Ensure the input contains only base32 alphabet characters A-Z and 2-7 (spaces are tolerated and stripped).","Remove any '=' padding, dashes, or non-base32 symbols from the secret.","If you have a hex or base64 secret, convert it to base32 first using the From Hex / From Base64 operations."],"exampleFix":"// before (hex secret passed directly)\nJBSWY3DPEHPK3PXP -> error if it contains '1','8','9','0'\n// after\nconst clean = secret.toUpperCase().replace(/[^A-Z2-7]/g, \"\");\n// feed only clean base32 to the operation","handlingStrategy":"validation","validationCode":"const BASE32 = /^[A-Z2-7]+$/;\nconst cleaned = secretStr.toUpperCase().replace(/\\s+/g, \"\");\nif (secretStr && !BASE32.test(cleaned)) {\n  // do not call the operation; surface a base32 error to the user\n}","typeGuard":"function isValidBase32Secret(s) {\n  if (!s) return true; // empty is allowed (random secret)\n  return /^[A-Z2-7]+$/.test(s.toUpperCase().replace(/\\s+/g, \"\"));\n}","tryCatchPattern":"try {\n  return OTPAuth.Secret.fromBase32(cleaned);\n} catch {\n  throw new OperationError(\"Invalid secret. Use base32 A-Z and 2-7.\");\n}","preventionTips":["Normalize the secret to uppercase and strip whitespace before passing it in.","Validate against /^[A-Z2-7]+$/ before invoking the operation.","Convert hex/base64 secrets to base32 with the appropriate decode operations first."],"tags":["otp","base32","hotp","user-input","argument-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}