rules:
  - id: auth.java.crypto.noop-password-encoder
    languages:
      - java
    severity: ERROR
    message: |
      Spring stores passwords with no hashing.

      `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.
    # Two literal sinks: the singleton no-op encoder and the deprecated
    # User.withDefaultPasswordEncoder() builder helper. Both are tight enough
    # that a match is always a real plaintext-password configuration.
    pattern-either:
      - pattern: NoOpPasswordEncoder.getInstance()
      - pattern: $U.withDefaultPasswordEncoder()
    metadata:
      oauthlint-rule-id: AUTH-JAVA-CRYPTO-005
      oauthlint-doc-url: https://oauthlint.dev/rules/java-crypto-noop-password-encoder
      category: security
      cwe: CWE-256
      owasp: A02:2021
      llm-prevalence: HIGH
      technology:
        - spring-security
      references:
        - https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html
        - https://cwe.mitre.org/data/definitions/256.html
