{"record":{"id":"27b9ce2cda98a10a","repo":"spring-projects/spring-security","slug":"bad-strength","errorCode":null,"errorMessage":"Bad strength","messagePattern":"Bad strength","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.java","lineNumber":106,"sourceCode":"\t/**\n\t * Creates a new instance using the given bcrypt version and strength.\n\t * @param version the version of bcrypt, can be 2a,2b,2y\n\t * @param strength the log rounds to use, between 4 and 31\n\t */\n\tpublic BCryptPasswordEncoder(BCryptVersion version, int strength) {\n\t\tthis(version, strength, null);\n\t}\n\n\t/**\n\t * Creates a new instance using the given bcrypt version, strength, and secure random\n\t * instance.\n\t * @param version the version of bcrypt, can be 2a,2b,2y\n\t * @param strength the log rounds to use, between 4 and 31\n\t * @param random the secure random instance to use\n\t */\n\tpublic BCryptPasswordEncoder(BCryptVersion version, int strength, @Nullable SecureRandom random) {\n\t\tif (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) {\n\t\t\tthrow new IllegalArgumentException(\"Bad strength\");\n\t\t}\n\t\tthis.version = version;\n\t\tthis.strength = (strength == -1) ? 10 : strength;\n\t\tthis.random = (random != null) ? () -> random : SecureRandomHolder::getInstance;\n\t}\n\n\t@Override\n\tprotected String encodeNonNullPassword(String rawPassword) {\n\t\tString salt = getSalt();\n\t\treturn BCrypt.hashpw(rawPassword.toString(), salt);\n\t}\n\n\tprivate String getSalt() {\n\t\treturn BCrypt.gensalt(this.version.getVersion(), this.strength, this.random.get());\n\t}\n\n\t@Override\n\tprotected boolean matchesNonNull(String rawPassword, String encodedPassword) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.java#L88-L124","documentation":"The BCryptPasswordEncoder constructor validates the requested strength (log rounds) when explicitly provided. It must be either -1 (meaning 'use the default of 10') or within BCrypt.MIN_LOG_ROUNDS (4) to BCrypt.MAX_LOG_ROUNDS (31). Anything else throws IllegalArgumentException at construction time.","triggerScenarios":"new BCryptPasswordEncoder(BCryptVersion.$2A, strength, random) where strength is, e.g., 0, 3, 32, or 100 — typically from externalized configuration or a computed value — while not being exactly -1.","commonSituations":"Spring @Value(\"${bcrypt.strength}\") injecting an unvalidated property; storing strength as a percentage (e.g. 80); front-end sending cost as bits instead of rounds; typos like -11.","solutions":["Use a strength between 4 and 31 (or -1 for the default).","Validate the configured integer before constructing the encoder.","Omit the strength parameter and use the no-arg or (version) constructor if defaults are fine."],"exampleFix":"// before\nint strength = Integer.parseInt(env.getProperty(\"security.bcrypt.strength\"));\nPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptVersion.$2A, strength);\n// after\nint raw = Integer.parseInt(env.getProperty(\"security.bcrypt.strength\"));\nif (raw != -1 && (raw < 4 || raw > 31)) throw new IllegalStateException(\"bcrypt strength must be 4-31 or -1\");\nPasswordEncoder encoder = new BCryptPasswordEncoder(BCryptVersion.$2A, raw);","handlingStrategy":"validation","validationCode":"if (strength != -1 && (strength < 4 || strength > 31)) throw new IllegalStateException(\"strength must be 4-31 or -1: \" + strength);","typeGuard":null,"tryCatchPattern":"try { encoder = new BCryptPasswordEncoder(version, strength, random); } catch (IllegalArgumentException e) { throw new IllegalStateException(\"Invalid bcrypt strength configuration: \" + strength, e); }","preventionTips":["Validate @Value-injected strength properties at application startup (fail-fast bean validation).","Use -1 sentinel or omit the parameter for defaults.","Never compute strength from percentages or bit sizes; store plain log-round integers."],"tags":["bcrypt","invalid-constructor-argument","spring-security","value-out-of-range"],"backgroundTag":"invalid-constructor-argument","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"}