diff --git a/src/dashboard/routes/agents.py b/src/dashboard/routes/agents.py index 6e4e5e4d..c7bf4789 100644 --- a/src/dashboard/routes/agents.py +++ b/src/dashboard/routes/agents.py @@ -63,6 +63,11 @@ async def clear_history(request: Request): @router.post("/default/chat", response_class=HTMLResponse) async def chat_agent(request: Request, message: str = Form(...)): """Chat — synchronous response.""" + message = message.strip() + if not message: + from fastapi import HTTPException + raise HTTPException(status_code=400, detail="Message cannot be empty") + timestamp = datetime.now().strftime("%H:%M:%S") response_text = None error_text = None diff --git a/src/dashboard/routes/memory.py b/src/dashboard/routes/memory.py index 6b0629b1..c082b20e 100644 --- a/src/dashboard/routes/memory.py +++ b/src/dashboard/routes/memory.py @@ -62,6 +62,10 @@ async def memory_search( context_type: Optional[str] = Form(None), ): """Search memories (form submission).""" + query = query.strip() + if not query: + raise HTTPException(status_code=400, detail="Search query cannot be empty") + results = search_memories( query=query, context_type=context_type, @@ -86,6 +90,10 @@ async def add_fact( agent_id: Optional[str] = Form(None), ): """Add a personal fact to memory.""" + fact = fact.strip() + if not fact: + raise HTTPException(status_code=400, detail="Fact content cannot be empty") + store_personal_fact(fact, agent_id=agent_id) facts = recall_personal_facts_with_ids()[:10] diff --git a/src/dashboard/routes/tasks.py b/src/dashboard/routes/tasks.py index 22293742..21154559 100644 --- a/src/dashboard/routes/tasks.py +++ b/src/dashboard/routes/tasks.py @@ -224,6 +224,10 @@ async def create_task_form( assigned_to: str = Form(""), ): """Create a task from the modal form and return a task card partial.""" + title = title.strip() + if not title: + raise HTTPException(status_code=400, detail="Task title cannot be empty") + task_id = str(uuid.uuid4()) now = datetime.utcnow().isoformat() priority = priority if priority in VALID_PRIORITIES else "normal" diff --git a/tests/dashboard/test_input_validation.py b/tests/dashboard/test_input_validation.py index 6a433974..0e31a525 100644 --- a/tests/dashboard/test_input_validation.py +++ b/tests/dashboard/test_input_validation.py @@ -20,9 +20,8 @@ def test_agents_chat_empty_message_validation(client): data={"message": ""}, headers={"X-CSRF-Token": csrf_token} if csrf_token else {}, ) - # Empty message should either be rejected or handled gracefully - # For now, we'll accept it but it should be logged - assert response.status_code in [200, 422] + # Empty message should be rejected + assert response.status_code in [400, 422] def test_agents_chat_oversized_message_validation(client): @@ -53,7 +52,7 @@ def test_memory_search_empty_query_validation(client): data={"query": ""}, headers={"X-CSRF-Token": csrf_token} if csrf_token else {}, ) - assert response.status_code in [200, 422, 500] # 500 for missing template + assert response.status_code in [400, 422, 500] # 500 for missing template def test_memory_search_oversized_query_validation(client):