hashing-passwords
CRITICAL security skill teaching proper credential and password handling. NEVER store passwords, use bcrypt/argon2, NEVER accept third-party credentials. Use when handling authentication, passwords, API keys, or any sensitive credentials.
When & Why to Use This Skill
This Claude skill acts as a critical security guardrail, enforcing industry-standard practices for credential and password handling. It prevents common security pitfalls by mandating the use of robust hashing algorithms like bcrypt and argon2, ensuring secure API key management via environment variables, and requiring OAuth for third-party integrations, thereby eliminating plaintext storage and weak encryption vulnerabilities.
Use Cases
- Secure User Authentication: Implementing signup and login flows that use bcrypt or argon2 for salted password hashing instead of plaintext or weak algorithms like MD5.
- API Key Management: Transitioning from hardcoded secrets to secure environment variable storage and secret management services to prevent credential leaks.
- Third-Party Integration: Replacing direct password requests for external services with secure OAuth 2.0 flows and token-based access to maintain user privacy.
- Security Auditing and Refactoring: Identifying and fixing insecure patterns in existing codebases, such as using Base64 encoding as a substitute for actual encryption.
| name | hashing-passwords |
|---|---|
| description | CRITICAL security skill teaching proper credential and password handling. NEVER store passwords, use bcrypt/argon2, NEVER accept third-party credentials. Use when handling authentication, passwords, API keys, or any sensitive credentials. |
| allowed-tools | Read, Write, Edit, Glob, Grep, Bash, Task, TodoWrite |
| version | 1.0.0 |
THIS IS A ZERO-TOLERANCE SECURITY SKILL. NO EXCEPTIONS.
This skill activates when:- Working with passwords or authentication
- Handling API keys, tokens, or credentials
- Storing sensitive user data
- Implementing login, signup, or password reset
- User mentions passwords, credentials, encryption, hashing, or authentication
- Code contains password storage, credential handling, or third-party auth
RULE 1: NEVER STORE PASSWORDS
Store password HASHES only, using bcrypt or argon2. Passwords must be:
- Hashed (NOT encrypted, NOT Base64, NOT plaintext)
- Salted automatically by bcrypt/argon2
- Using modern algorithms (bcrypt cost 12+, argon2id)
RULE 2: NEVER ACCEPT THIRD-PARTY CREDENTIALS
NEVER ask users for passwords to other services (PayPal, Google, etc.):
- Use OAuth instead
- Use API keys from the service
- Use service-provided SDKs
RULE 3: NEVER USE ENCODING AS ENCRYPTION
- Base64 is NOT encryption (trivially reversible)
- URL encoding is NOT security
- Hex encoding is NOT security
RULE 4: USE PROPER CRYPTOGRAPHY
- For passwords: bcrypt or argon2
- For encryption: Use established libraries (crypto module, Web Crypto API)
- For API keys: Store in environment variables, use secret management
❌ Base64 "Encryption": Buffer.from(password).toString("base64") is encoding, NOT encryption. Trivially reversible.
❌ Third-Party Passwords: Never accept PayPal/Google/etc passwords. Use OAuth.
❌ Plaintext Storage: Never store raw passwords. Always hash.
❌ Weak Hashing: MD5/SHA-1/SHA-256 too fast. Use bcrypt/argon2.
See references/never-do-this.md for detailed examples and failures.
import bcrypt from "bcrypt";
const SALT_ROUNDS = 12;
async function hashPassword(password: string): Promise<string> {
return await bcrypt.hash(password, SALT_ROUNDS);
}
async function verifyPassword(
password: string,
hash: string
): Promise<boolean> {
return await bcrypt.compare(password, hash);
}
interface User {
id: string;
email: string;
passwordHash: string;
}
Key Points:
- bcrypt designed for passwords
- Automatic salting
- Cost factor 12+ (prevents brute force)
- Never stores actual password
✅ CORRECT: argon2 (More Modern)
import argon2 from "argon2";
async function hashPassword(password: string): Promise<string> {
return await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 2 ** 16,
timeCost: 3,
parallelism: 1
});
}
Advantages: Memory-hard, resists GPU attacks, latest standard.
✅ CORRECT: OAuth for Third-Party Services
import { google } from "googleapis";
const oauth2Client = new google.auth.OAuth2(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
"http://localhost:3000/auth/callback"
);
function getAuthUrl(): string {
return oauth2Client.generateAuthUrl({
access_type: "offline",
scope: ["https://www.googleapis.com/auth/userinfo.email"]
});
}
Key Points: Token-based, never sees user password, revocable.
✅ CORRECT: Environment Variables for API Keys
function loadConfig(): Config {
const apiKey = process.env.STRIPE_API_KEY;
if (!apiKey) {
throw new Error("Missing required API key");
}
return { apiKey };
}
See references/correct-implementations.md for complete examples.
- Use bcrypt (cost 12+) or argon2id for password hashing
- Store password HASHES only, never passwords
- Use OAuth for third-party service authentication
- Store API keys in environment variables
- Validate password strength (min length, complexity)
- Use HTTPS for all authentication endpoints
NEVER:
- Store passwords in any form (plaintext, Base64, encrypted)
- Use MD5, SHA-1, or SHA-256 for passwords
- Accept third-party credentials (PayPal, Google, etc.)
- Hardcode API keys or secrets
- Use encoding (Base64, hex) as "encryption"
- Email passwords to users
- Log passwords (even in dev mode)
SHOULD:
- Implement password strength requirements
- Rate-limit login attempts
- Use two-factor authentication (2FA)
- Implement account lockout after failed attempts
- Rotate API keys periodically
- Use secret management services (AWS Secrets Manager, HashiCorp Vault)
- Length: 12+ characters (prefer 16+)
- Complexity: Uppercase, lowercase, numbers, special chars
- Validation: Reject common passwords ("password", "12345678")
See references/password-validation.md for complete implementation.
bcrypt:
npm install bcrypt
npm install -D @types/bcrypt
argon2:
npm install argon2
npm install -D @types/argon2
Note: Both require native compilation. Ensure build tools are available.
## Reference FilesDetailed Examples:
references/never-do-this.md- Security failures and anti-patternsreferences/correct-implementations.md- Complete working examplesreferences/password-validation.md- Password strength validationreferences/emergency-response.md- Breach response and migration
Related Skills:
- Input Validation: Use the sanitizing-user-inputs skill
- Dependencies: Use the auditing-dependencies skill
- External Data: Use the validating-external-data skill
Password Storage:
- Uses bcrypt (cost 12+) or argon2id
- NEVER stores actual passwords
- Password hashes stored in separate column
- No way to retrieve original password
Third-Party Auth:
- Uses OAuth/OpenID Connect
- NEVER asks for third-party passwords
- Tokens stored securely
- Follows service Terms of Service
API Keys:
- Stored in environment variables
- Not hardcoded in source
- Not committed to git
-
.envfile in.gitignore
Password Requirements:
- Minimum 12 characters (prefer 16+)
- Complexity requirements enforced
- Common passwords rejected
- Strength meter for users
Additional Security:
- HTTPS required for auth endpoints
- Rate limiting on login
- Account lockout after failures
- Password reset via email only
- No password hints or security questions
"I need to retrieve the password later" → You never need to retrieve passwords. Use password reset instead.
"Base64 is encryption" → Base64 is encoding for transport, not security.
"I'll encrypt passwords" → If you can decrypt, so can attackers. Hash, don't encrypt.
"SHA-256 is secure" → SHA-256 is too fast. Use bcrypt/argon2.
"I need PayPal credentials to check balance" → Use PayPal's API with OAuth tokens.
## If You Find Insecure Password StorageIMMEDIATE ACTIONS:
- Stop the application (if running)
- Do NOT commit the code
- Implement proper hashing (bcrypt/argon2)
- Force password reset for all users
- Notify security team
- Assess breach scope
See references/emergency-response.md for complete migration guide.