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.go.crypto.weak-password-hash

A password is being hashed with a fast, general-purpose digest from the Go standard library (MD5, SHA-1, SHA-256, SHA-512).

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

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: bcrypt (golang.org/x/crypto/bcrypt.GenerateFromPassword), Argon2 (golang.org/x/crypto/argon2.IDKey), or scrypt (golang.org/x/crypto/scrypt.Key). These resist brute-force by design.

VULNERABLE
vulnerable.go
package main

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"fmt"
)

func hashWithMD5(password string) [16]byte {
	// ruleid: auth.go.crypto.weak-password-hash
	return md5.Sum([]byte(password))
}

func hashWithSHA1(password string) [20]byte {
	// ruleid: auth.go.crypto.weak-password-hash
	return sha1.Sum([]byte(password))
}

func hashWithSHA256(password string) [32]byte {
	// ruleid: auth.go.crypto.weak-password-hash
	return sha256.Sum256([]byte(password))
}

func hashWithWriter(password string) []byte {
	h := sha256.New()
	// ruleid: auth.go.crypto.weak-password-hash
	h.Write([]byte(password))
	return h.Sum(nil)
}

func main() {
	fmt.Println(
		hashWithMD5("hunter2"),
		hashWithSHA1("hunter2"),
		hashWithSHA256("hunter2"),
		hashWithWriter("hunter2"),
	)
}
SAFE
safe.go
package main

import (
	"crypto/sha256"
	"fmt"

	"golang.org/x/crypto/bcrypt"
)

// Secure: passwords are hashed with bcrypt, a slow, salted password hasher.
func hashPassword(password string) ([]byte, error) {
	// ok: auth.go.crypto.weak-password-hash
	return bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
}

// Non-password use of a fast digest: checksumming file contents. Not flagged.
func checksum(fileBytes []byte) [32]byte {
	// ok: auth.go.crypto.weak-password-hash
	return sha256.Sum256(fileBytes)
}

func main() {
	hash, _ := hashPassword("hunter2")
	fmt.Println(hash, checksum([]byte("file contents")))
}

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.go.crypto.weak-password-hash -- <reason>

References

https://cwe.mitre.org/data/definitions/916.html ↗https://pkg.go.dev/golang.org/x/crypto/bcrypt ↗https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html ↗