v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.java.crypto.noop-password-encoder

Spring stores passwords with no hashing.

Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.

Why this matters

NoOpPasswordEncoder keeps passwords in plaintext and withDefaultPasswordEncoder() is a builder helper that Spring explicitly marks for non-production use only. Either way the stored credential is not hashed, so anyone who reads the database or a backup recovers every password directly (CWE-256). This is a common AI-generated shortcut: the no-op encoder is pasted in to "get login working" and never replaced.

Hash passwords with a dedicated, slow, salted algorithm. Use new BCryptPasswordEncoder(), Argon2PasswordEncoder, or Pbkdf2PasswordEncoder instead. A DelegatingPasswordEncoder built via PasswordEncoderFactories.createDelegatingPasswordEncoder() is the recommended default.

VULNERABLE
vulnerable.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
class SecurityConfig {

    @Bean
    PasswordEncoder passwordEncoder() {
        // ruleid: auth.java.crypto.noop-password-encoder
        return NoOpPasswordEncoder.getInstance();
    }

    UserDetails user() {
        // ruleid: auth.java.crypto.noop-password-encoder
        return User.withDefaultPasswordEncoder()
            .username("admin")
            .password("admin")
            .roles("ADMIN")
            .build();
    }
}
SAFE
safe.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
class SecurityConfig {

    // ok: auth.java.crypto.noop-password-encoder -- BCrypt is a proper password hasher
    @Bean
    PasswordEncoder bcryptEncoder() {
        return new BCryptPasswordEncoder();
    }

    // ok: auth.java.crypto.noop-password-encoder -- Argon2 is a proper password hasher
    PasswordEncoder argon2Encoder() {
        return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
    }
}

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.java.crypto.noop-password-encoder -- <reason>

References

https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html ↗https://cwe.mitre.org/data/definitions/256.html ↗