{"record":{"id":"fb096873b5050d37","repo":"spring-projects/spring-security","slug":"invalid-prefix","errorCode":null,"errorMessage":"Invalid prefix","messagePattern":"Invalid prefix","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java","lineNumber":692,"sourceCode":"\t\treturn rs.toString();\n\t}\n\n\t/**\n\t * Generate a salt for use with the BCrypt.hashpw() method\n\t * @param prefix the prefix value (default $2a)\n\t * @param log_rounds the log2 of the number of rounds of hashing to apply - the work\n\t * factor therefore increases as 2**log_rounds.\n\t * @param random an instance of SecureRandom to use\n\t * @return an encoded salt value\n\t * @exception IllegalArgumentException if prefix or log_rounds is invalid\n\t */\n\tpublic static String gensalt(String prefix, int log_rounds, SecureRandom random) throws IllegalArgumentException {\n\t\tStringBuilder rs = new StringBuilder();\n\t\tbyte rnd[] = new byte[BCRYPT_SALT_LEN];\n\n\t\tif (!prefix.startsWith(\"$2\")\n\t\t\t\t|| (prefix.charAt(2) != 'a' && prefix.charAt(2) != 'y' && prefix.charAt(2) != 'b')) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid prefix\");\n\t\t}\n\t\tif (log_rounds < 4 || log_rounds > 31) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid log_rounds\");\n\t\t}\n\n\t\trandom.nextBytes(rnd);\n\n\t\trs.append(\"$2\");\n\t\trs.append(prefix.charAt(2));\n\t\trs.append(\"$\");\n\t\tif (log_rounds < 10) {\n\t\t\trs.append(\"0\");\n\t\t}\n\t\trs.append(log_rounds);\n\t\trs.append(\"$\");\n\t\tencode_base64(rnd, rnd.length, rs);\n\t\treturn rs.toString();\n\t}","sourceCodeStart":674,"sourceCodeEnd":710,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java#L674-L710","documentation":"BCrypt.gensalt throws this when the salt prefix string is not a valid BCrypt identifier. A valid prefix must start with \"$2\" and its third character must be 'a', 'y', or 'b' (the supported BCrypt versions 2a, 2y, 2b). The library throws IllegalArgumentException to fail fast rather than emitting a salt that no BCrypt implementation can verify.","triggerScenarios":"Calling BCrypt.gensalt(prefix, log_rounds, random) with a prefix like \"$1\" (MD5 crypt), \"$2\" with no version char, \"$2c\", \"$2x\", or an empty string — anything failing the startsWith(\"$2\") or charAt(2) in {'a','y','b'} check.","commonSituations":"Porting salt strings from other crypt implementations (e.g. $1$ or $6$ prefixes from glibc crypt), hand-copying hashed salts truncated to two characters, or passing a full hash as the prefix instead of just the \"$2a\" portion.","solutions":["Pass one of the exact prefixes \"$2a\", \"$2y\", or \"$2b\" (or use BCryptPasswordEncoder's BCryptVersion enum instead of a raw string).","If you have an existing encoded hash, extract the prefix via hash.substring(0, 3) rather than passing the whole hash.","Validate prefix.startsWith(\"$2\") && \"ayb\".indexOf(prefix.charAt(2)) >= 0 before calling to fail with a clearer message."],"exampleFix":"// before\nBCrypt.gensalt(\"$2x\", 10);\n// after\nBCrypt.gensalt(\"$2a\", 10); // or BCrypt.gensalt(BCrypt.BCryptVersion.$2A)","handlingStrategy":"validation","validationCode":"boolean validPrefix(String p) { return p != null && p.length() >= 3 && p.startsWith(\"$2\") && (p.charAt(2)=='a' || p.charAt(2)=='y' || p.charAt(2)=='b'); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use BCrypt.BCryptVersion enum or BCryptPasswordEncoder instead of raw prefix strings.","Never pass a full hash or a foreign crypt prefix where a BCrypt prefix is expected.","Extract prefixes from stored hashes with substring(0, 3) only after format validation."],"tags":["bcrypt","invalid-argument","spring-security","crypto"],"backgroundTag":"invalid-argument-value","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}