π Description
The UserRegister Pydantic schema in backend/app/schemas.py accepts any value for the password field β including an empty string β with no length, format, or complexity validation. The backend bcrypt-hashes whatever it receives, meaning users can successfully register with password: "".
π Steps to Reproduce
- Start the backend server
- Send a
POST /api/auth/register request with an empty or single-character password:
curl -X POST http://localhost:8000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "testuser", "email": "test@example.com", "password": ""}'
- Observe that the server returns
201 Created and a valid JWT token
π» Expected Behavior
The API should reject weak passwords with a 422 Unprocessable Entity response and a clear error message before the password ever reaches the bcrypt hashing layer.
π§ Actual Behavior
backend/app/schemas.py:
class UserRegister(BaseModel):
username: str
email: EmailStr
password: str # no min_length, no complexity requirement
Any string (including "") passes validation and gets stored as a bcrypt hash in the database.
πΌοΈ Screenshots / Logs (if applicable)
File: backend/app/schemas.py β UserRegister class
The password field has no Field(min_length=...) constraint or validator.
π§© Environment
- Backend: FastAPI + Pydantic
- File:
backend/app/schemas.py
π§© Possible Fix
Use Pydantic Field and field_validator to enforce minimum length and basic complexity:
from pydantic import BaseModel, EmailStr, Field, field_validator
import re
class UserRegister(BaseModel):
username: str = Field(min_length=3, max_length=30)
email: EmailStr
password: str = Field(min_length=8, max_length=128)
@field_validator("password")
@classmethod
def password_complexity(cls, v: str) -> str:
if not re.search(r"[A-Z]", v):
raise ValueError("Password must contain at least one uppercase letter.")
if not re.search(r"\d", v):
raise ValueError("Password must contain at least one digit.")
return v
Why it matters: Backend APIs must enforce their own invariants β frontend validation is bypassable via direct API calls. Bcrypt happily hashes an empty string, creating valid accounts with no real security.
β
Checklist
π Description
The
UserRegisterPydantic schema inbackend/app/schemas.pyaccepts any value for thepasswordfield β including an empty string β with no length, format, or complexity validation. The backend bcrypt-hashes whatever it receives, meaning users can successfully register withpassword: "".π Steps to Reproduce
POST /api/auth/registerrequest with an empty or single-character password:201 Createdand a valid JWT tokenπ» Expected Behavior
The API should reject weak passwords with a
422 Unprocessable Entityresponse and a clear error message before the password ever reaches the bcrypt hashing layer.π§ Actual Behavior
backend/app/schemas.py:Any string (including
"") passes validation and gets stored as a bcrypt hash in the database.πΌοΈ Screenshots / Logs (if applicable)
File:
backend/app/schemas.pyβUserRegisterclassThe
passwordfield has noField(min_length=...)constraint or validator.π§© Environment
backend/app/schemas.pyπ§© Possible Fix
Use Pydantic
Fieldandfield_validatorto enforce minimum length and basic complexity:Why it matters: Backend APIs must enforce their own invariants β frontend validation is bypassable via direct API calls. Bcrypt happily hashes an empty string, creating valid accounts with no real security.
β Checklist