cursorrules / rules
ivangrynenko/cursorrules/.cursor/rules/python-authentication-failures.mdc
Detect and prevent identification and authentication failures in Python applications as defined in OWASP Top 10:2021-A07
Cursor rule88 starsChanged 11 months ago
- Reads credentials
---
description: Detect and prevent identification and authentication failures in Python applications as defined in OWASP Top 10:2021-A07
globs: *.py, *.ini, *.cfg, *.yml, *.yaml, *.json, *.toml
alwaysApply: false
---
# Python Identification and Authentication Failures Standards (OWASP A07:2021)
This rule enforces security best practices to prevent identification and authentication failures in Python applications, as defined in OWASP Top 10:2021-A07.
<rule>
name: python_authentication_failures
description: Detect and prevent identification and authentication failures in Python applications as defined in OWASP Top 10:2021-A07
filters:
- type: file_extension
pattern: "\\.(py|ini|cfg|yml|yaml|json|toml)$"
- type: file_path
pattern: ".*"
actions:
- type: enforce
conditions:
# Pattern 1: Weak password validation
- pattern: "password\\s*=\\s*['\"][^'\"]{1,7}['\"]|min_length\\s*=\\s*[1-7]"
message: "Weak password policy detected. Passwords should be at least 8 characters long and include complexity requirements."
# Pattern 2: Hardcoded credentials
- pattern: "(username|user|login|password|passwd|pwd|secret|api_key|apikey|token)\\s*=\\s*['\"][^'\"]+['\"]"
message: "Hardcoded credentials detected. Store sensitive credentials in environment variables or a secure vault."
# Pattern 3: Missing password hashing
- pattern: "password\\s*=\\s*request\\.form\\[\\'password\\'\\]|password\\s*=\\s*request\\.POST\\.get\\(\\'password\\'\\)"
message: "Storing or comparing plain text passwords detected. Always hash passwords before storage or comparison."
# Pattern 4: Insecure password hashing
- pattern: "hashlib\\.md5\\(|hashlib\\.sha1\\(|hashlib\\.sha224\\("
message: "Insecure hashing algorithm detected. Use strong hashing algorithms like bcrypt, Argon2, or PBKDF2."
# Pattern 5: Missing brute force protection
- pattern: "@app\\.route\\(['\"]\\/(login|signin|authenticate)['\"]"
message: "Authentication endpoint detected without rate limiting or brute force protection. Implement account lockout or rate limiting."
# Pattern 6: Insecure session management
- pattern: "session\\[\\'user_id\\'\\]\\s*=|session\\[\\'authenticated\\'\\]\\s*=\\s*True"
message: "Session management detected. Ensure proper session security with secure cookies, proper expiration, and rotation."
# Pattern 7: Missing CSRF protection in authentication
- pattern: "form\\s*=\\s*FlaskForm|class\\s+\\w+Form\\(\\s*FlaskForm\\s*\\)|class\\s+\\w+Form\\(\\s*Form\\s*\\)"
message: "Form handling detected. Ensure CSRF protection is enabled for all authentication forms."
# Pattern 8: Insecure remember me functionality
- pattern: "remember_me|remember_token|stay_logged_in"
message: "Remember me functionality detected. Ensure secure implementation with proper expiration and refresh mechanisms."
# Pattern 9: Insecure password reset
- pattern: "@app\\.route\\(['\"]\\/(reset-password|forgot-password|recover)['\"]"
message: "Password reset functionality detected. Ensure secure implementation with time-limited tokens and proper user verification."
# Pattern 10: Missing multi-factor authentication
- pattern: "def\\s+login|def\\s+authenticate|def\\s+signin"
message: "Authentication function detected. Consider implementing multi-factor authentication for sensitive operations."
# Pattern 11: Insecure direct object reference in user management
- pattern: "User\\.objects\\.get\\(id=|User\\.query\\.get\\(|get_user_by_id\\("
message: "Direct user lookup detected. Ensure proper authorization checks before accessing user data."
# Pattern 12: Insecure JWT implementation
- pattern: "jwt\\.encode\\(|jwt\\.decode\\("
message: "JWT usage detected. Ensure proper signing, validation, expiration, and refresh mechanisms for JWTs."
# Pattern 13: Missing secure flag in cookies
- pattern: "set_cookie\\([^,]+,[^,]+,[^,]*secure=False|set_cookie\\([^,]+,[^,]+(?!,\\s*secure=True)"
message: "Cookie setting without secure flag detected. Set secure=True for all authentication cookies."
# Pattern 14: Missing HTTP-only flag in cookies
- pattern: "set_cookie\\([^,]+,[^,]+,[^,]*httponly=False|set_cookie\\([^,]+,[^,]+(?!,\\s*httponly=True)"
message: "Cookie setting without httponly flag detected. Set httponly=True for all authentication cookies."
# Pattern 15: Insecure default credentials
- pattern: "DEFAULT_USERNAME|DEFAULT_PASSWORD|ADMIN_USERNAME|ADMIN_PASSWORD"
message: "Default credential configuration detected. Remove default credentials from production code."
- type: suggest
message: |
**Python Authentication Security Best Practices:**
1. **Password Storage:**
- Use strong hashing algorithms with salting
- Implement proper work factors
- Example with passlib:
```python
from passlib.hash import argon2
# Hash a password
hashed_password = argon2.hash("user_password")
# Verify a password
is_valid = argon2.verify("user_password", hashed_password)
```
- Example with Django:
```python
from django.contrib.auth.hashers import make_password, check_password
# Hash a password
hashed_password = make_password("user_password")
# Verify a password
is_valid = check_password("user_password", hashed_password)
```
2. **Password Policies:**
- Enforce minimum length (at least 8 characters)
- Require complexity (uppercase, lowercase, numbers, special characters)
- Check against common passwords
- Example with Django:
```python
# settings.py
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {'min_length': 12}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
]
```
3. **Brute Force Protection:**
- Implement account lockout after failed attempts
- Use rate limiting for authentication endpoints
- Example with Flask and Flask-Limiter:
```python
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route("/login", methods=["POST"])
@limiter.limit("5 per minute")
def login():
# Login logic here
pass
```
4. **Multi-Factor Authentication:**
- Implement MFA for sensitive operations
- Use time-based one-time passwords (TOTP)
- Example with pyotp:
```python
import pyotp
# Generate a secret key for the user
secret = pyotp.random_base32()
# Create a TOTP object
totp = pyotp.TOTP(secret)
# Verify a token
is_valid = totp.verify(user_provided_token)
```
5. **Secure Session Management:**
- Use secure, HTTP-only cookies
- Implement proper session expiration
- Rotate session IDs after login
- Example with Flask:
```python
from flask import Flask, session
app = Flask(__name__)
app.config.update(
SECRET_KEY='your-secret-key',
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
PERMANENT_SESSION_LIFETIME=timedelta(hours=1)
)
```
6. **CSRF Protection:**
- Implement CSRF tokens for all forms
- Validate tokens on form submission
- Example with Flask-WTF:
```python
from flask_wtf import FlaskForm, CSRFProtect
from wtforms import StringField, PasswordField, SubmitField
csrf = CSRFProtect(app)
class LoginForm(FlaskForm):
username = StringField('Username')
password = PasswordField('Password')
submit = SubmitField('Login')
```
7. **Secure Password Reset:**
- Use time-limited, single-use tokens
- Send reset links to verified email addresses
- Example implementation:
```python
import secrets
from datetime import datetime, timedelta
def generate_reset_token(user_id):
token = secrets.token_urlsafe(32)
expiry = datetime.utcnow() + timedelta(hours=1)
# Store token and expiry in database with user_id
return token
def verify_reset_token(token):
# Retrieve token from database
# Check if token exists and is not expired
# If valid, return user_id
pass
```
8. **Secure JWT Implementation:**
- Use strong signing keys
- Include expiration claims
- Validate all claims
- Example with PyJWT:
```python
import jwt
from datetime import datetime, timedelta
# Create a JWT
payload = {
'user_id': user.id,
'exp': datetime.utcnow() + timedelta(hours=1),
'iat': datetime.utcnow()
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
# Verify a JWT
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
user_id = payload['user_id']
except jwt.ExpiredSignatureError:
# Token has expired
pass
except jwt.InvalidTokenError:
# Invalid token
pass
```
9. **Secure Cookie Configuration:**
- Set secure, HTTP-only, and SameSite flags
- Example with Flask:
```python
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/set_cookie')
def set_cookie():
resp = make_response('Cookie set')
resp.set_cookie(
'session_id',
'value',
secure=True,
httponly=True,
samesite='Lax',
max_age=3600
)
return resp
```
10. **Credential Storage:**
- Use environment variables or secure vaults
- Never hardcode credentials
- Example with python-dotenv:
```python
import os
from dotenv import load_dotenv
load_dotenv()
# Access credentials from environment variables
db_user = os.environ.get('DB_USER')
db_password = os.environ.get('DB_PASSWORD')
```
- type: validate
conditions:
# Check 1: Proper password hashing
- pattern: "argon2|bcrypt|pbkdf2|make_password|generate_password_hash"
message: "Using secure password hashing algorithms."
# Check 2: CSRF protection
- pattern: "csrf|CSRFProtect|csrf_token|csrftoken"
message: "CSRF protection is implemented."
# Check 3: Secure cookie settings
- pattern: "SESSION_COOKIE_SECURE\\s*=\\s*True|secure=True|httponly=True|samesite"
message: "Secure cookie settings are configured."
# Check 4: Rate limiting
- pattern: "limiter\\.limit|RateLimitExceeded|rate_limit|throttle"
message: "Rate limiting is implemented for authentication endpoints."
metadata:
priority: high
version: 1.0
tags:
- security
- python
- authentication
- identity
- owasp
- language:python
- framework:django
- framework:flask
- framework:fastapi
- category:security
- subcategory:authentication
- standard:owasp-top10
- risk:a07-identification-authentication-failures
references:
- "https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/"
- "https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html"
- "https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html"
- "https://cheatsheetseries.owasp.org/cheatsheets/Credential_Stuffing_Prevention_Cheat_Sheet.html"
- "https://docs.djangoproject.com/en/stable/topics/auth/passwords/"
- "https://flask-login.readthedocs.io/en/latest/"
- "https://fastapi.tiangolo.com/tutorial/security/"
</rule>Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
Posts are public.Sign in to post
No one has posted yet. Be the first.

