rules:
  - id: auth.rust.crypto.weak-password-hash
    languages:
      - rust
    severity: ERROR
    message: |
      A password is hashed with a fast, general-purpose digest unsuitable for
      password storage. The digest is MD5 (via the `md5` crate) or
      SHA-1/SHA-256/SHA-512 (via the RustCrypto `sha1`/`sha2` crates). These
      algorithms are designed to be fast, which makes offline brute-force and
      rainbow-table attacks cheap; they are NOT suitable for storing passwords
      (CWE-916).

      Use a dedicated, slow password-hashing function with a per-password salt
      and a tunable work factor: Argon2 (`argon2` crate,
      `Argon2::default().hash_password(...)`), bcrypt (`bcrypt::hash(...)`), or
      scrypt (`scrypt` crate). These resist brute-force by design.
    # Anchored to the *password* character of the input: the digested/updated
    # argument must be named like a password (metavariable-regex on $PW). This
    # avoids flagging `Sha256::digest(file_bytes)` used for file checksums or
    # non-password fingerprints, and does not touch real password hashers
    # (argon2 / bcrypt / scrypt).
    patterns:
      - pattern-either:
          - pattern: md5::compute($PW)
          - pattern: Md5::digest($PW)
          - pattern: Sha1::digest($PW)
          - pattern: Sha256::digest($PW)
          - pattern: Sha512::digest($PW)
          - pattern: $H.update($PW)
      - metavariable-regex:
          metavariable: $PW
          regex: (?i).*(password|passwd|pwd).*
    metadata:
      oauthlint-rule-id: AUTH-RUST-CRYPTO-001
      oauthlint-doc-url: https://oauthlint.dev/rules/rust-crypto-weak-password-hash
      category: security
      cwe: CWE-916
      owasp: A02:2021
      llm-prevalence: HIGH
      technology:
        - sha2
        - md5
      references:
        - https://cwe.mitre.org/data/definitions/916.html
        - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
        - https://docs.rs/argon2/latest/argon2/
