fix: critical security hardening (Phase A permissions audit)
- Remove role field from UserCreate schema, hardcode 'engineer' at registration
- Escape all user content in HTML export with html.escape() (XSS fix)
- Add field_validator to reject default SECRET_KEY when DEBUG=False
- Add CHECK constraint on users.role ('engineer'|'viewer') + migration 011
- Fix test_admin fixture to properly grant is_super_admin via ORM
- Fix circular FK (users↔invite_codes) in test DB setup with DROP SCHEMA CASCADE
- Add 5 new security tests (role validation + XSS prevention)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
34
backend/alembic/versions/011_add_role_check_constraint.py
Normal file
34
backend/alembic/versions/011_add_role_check_constraint.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""add role check constraint to users
|
||||
|
||||
Revision ID: 011
|
||||
Revises: 010
|
||||
Create Date: 2026-02-05
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '011'
|
||||
down_revision: Union[str, None] = '010'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Normalize any remaining non-standard role values to 'engineer'
|
||||
# (migration 010 already converted 'admin' -> 'engineer', this is defense-in-depth)
|
||||
op.execute(
|
||||
"UPDATE users SET role = 'engineer' WHERE role NOT IN ('engineer', 'viewer')"
|
||||
)
|
||||
op.create_check_constraint(
|
||||
'ck_users_role_enum',
|
||||
'users',
|
||||
"role IN ('engineer', 'viewer')"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint('ck_users_role_enum', 'users', type_='check')
|
||||
Reference in New Issue
Block a user