Fix MEDIUM-HIGH Security Issue: Add input validation for choice fields

Added validation for status, priority, and recurrence fields in web forms to prevent invalid database values.

Changes:

TaskUpdateView.post() (line 419):
- Validate status against Task.STATUS_CHOICES before setting
- Validate priority against Task.PRIORITY_CHOICES before setting
- Validate recurrence against Task.RECURRENCE_CHOICES before setting
- Only update fields if value is in allowed choices
- Default to 'none' for invalid recurrence values

TaskCreateView.post() (line 481):
- Validate status, default to 'pending' if invalid
- Validate priority, default to 'medium' if invalid
- Validate recurrence, default to 'none' if invalid
- Prevents creation with invalid choice values

Allowed Choices:
- Status: pending, in_progress, completed, cancelled
- Priority: low, medium, high, urgent
- Recurrence: none, daily, weekly, biweekly, monthly

Security impact:
- Prevents invalid database values from user input
- Maintains data integrity
- Blocks potential business logic bypasses
- Prevents database constraint violations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Keith Smith
2025-12-23 06:25:22 -07:00
co-authored by Claude Sonnet 4.5
parent a03b9fe79c
commit 84d9b4704a
+40 -6
View File
@@ -424,8 +424,18 @@ class TaskDetailView(View):
task.title = request.POST.get('title', task.title) task.title = request.POST.get('title', task.title)
task.description = request.POST.get('description', '') task.description = request.POST.get('description', '')
task.status = request.POST.get('status', task.status)
task.priority = request.POST.get('priority', task.priority) # Validate status against allowed choices
status = request.POST.get('status', task.status)
valid_statuses = [choice[0] for choice in Task.STATUS_CHOICES]
if status in valid_statuses:
task.status = status
# Validate priority against allowed choices
priority = request.POST.get('priority', task.priority)
valid_priorities = [choice[0] for choice in Task.PRIORITY_CHOICES]
if priority in valid_priorities:
task.priority = priority
due_date = request.POST.get('due_date') due_date = request.POST.get('due_date')
task.due_date = due_date if due_date else None task.due_date = due_date if due_date else None
@@ -433,7 +443,13 @@ class TaskDetailView(View):
due_time = request.POST.get('due_time') due_time = request.POST.get('due_time')
task.due_time = due_time if due_time else None task.due_time = due_time if due_time else None
task.recurrence = request.POST.get('recurrence', 'none') # Validate recurrence against allowed choices
recurrence = request.POST.get('recurrence', 'none')
valid_recurrences = [choice[0] for choice in Task.RECURRENCE_CHOICES]
if recurrence in valid_recurrences:
task.recurrence = recurrence
else:
task.recurrence = 'none'
task.save() task.save()
@@ -466,15 +482,33 @@ class TaskCreateView(View):
if not request.user.is_authenticated: if not request.user.is_authenticated:
return redirect('login') return redirect('login')
# Validate status against allowed choices
status = request.POST.get('status', 'pending')
valid_statuses = [choice[0] for choice in Task.STATUS_CHOICES]
if status not in valid_statuses:
status = 'pending'
# Validate priority against allowed choices
priority = request.POST.get('priority', 'medium')
valid_priorities = [choice[0] for choice in Task.PRIORITY_CHOICES]
if priority not in valid_priorities:
priority = 'medium'
# Validate recurrence against allowed choices
recurrence = request.POST.get('recurrence', 'none')
valid_recurrences = [choice[0] for choice in Task.RECURRENCE_CHOICES]
if recurrence not in valid_recurrences:
recurrence = 'none'
task = Task.objects.create( task = Task.objects.create(
user=request.user, user=request.user,
title=request.POST.get('title'), title=request.POST.get('title'),
description=request.POST.get('description', ''), description=request.POST.get('description', ''),
status=request.POST.get('status', 'pending'), status=status,
priority=request.POST.get('priority', 'medium'), priority=priority,
due_date=request.POST.get('due_date') or None, due_date=request.POST.get('due_date') or None,
due_time=request.POST.get('due_time') or None, due_time=request.POST.get('due_time') or None,
recurrence=request.POST.get('recurrence', 'none'), recurrence=recurrence,
) )
tag_ids = request.POST.getlist('tags') tag_ids = request.POST.getlist('tags')