Skip to content

Commit 38a7002

Browse files
committed
fix(security): sanitize user-controlled data in logs to prevent log injection
- Use sanitize_log_data() for all user-controlled data before logging - Sanitize tool_id and message parameters in MCP router - Sanitize message text in MCP planner graph timeout and routing logs - Use sanitize_error_message() for HTTP error responses - Prevents log injection attacks by encoding suspicious data in base64 - Addresses SonarQube security warnings for log injection vulnerabilities
1 parent 5301855 commit 38a7002

2 files changed

Lines changed: 22 additions & 9 deletions

File tree

src/api/graphs/mcp_integrated_planner_graph.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from src.api.services.mcp.tool_routing import ToolRoutingService, RoutingStrategy
4242
from src.api.services.mcp.tool_validation import ToolValidationService
4343
from src.api.services.mcp.base import MCPManager
44+
from src.api.utils.log_utils import sanitize_log_data
4445

4546
logger = logging.getLogger(__name__)
4647

@@ -775,11 +776,13 @@ async def _mcp_route_intent(self, state: MCPWarehouseState) -> MCPWarehouseState
775776
for tool in available_tools
776777
]
777778

779+
# Sanitize user-controlled message before logging
780+
safe_message_text = sanitize_log_data(message_text, max_length=100)
778781
logger.info(
779-
f"🔀 MCP Intent classified as: {intent} for message: {message_text[:100]}..."
782+
f"🔀 MCP Intent classified as: {intent} for message: {safe_message_text}..."
780783
)
781784
logger.debug(
782-
f"Routing decision details - Intent: {intent}, Message: {message_text}, "
785+
f"Routing decision details - Intent: {intent}, Message: {safe_message_text}, "
783786
f"Safety keywords found: {sum(1 for kw in MCPIntentClassifier.SAFETY_KEYWORDS if kw in message_text.lower())}, "
784787
f"Equipment keywords found: {sum(1 for kw in MCPIntentClassifier.EQUIPMENT_KEYWORDS if kw in message_text.lower())}"
785788
)
@@ -1556,9 +1559,11 @@ async def process_warehouse_query(
15561559
)
15571560
logger.info(f"✅ Graph execution completed in time: timeout={graph_timeout}s")
15581561
except asyncio.TimeoutError:
1562+
# Sanitize user-controlled message before logging
1563+
safe_message = sanitize_log_data(message, max_length=100)
15591564
logger.error(
15601565
f"⏱️ TIMEOUT: Graph execution timed out after {graph_timeout}s | "
1561-
f"Message: {message[:100]} | Complex: {is_complex_query} | Reasoning: {enable_reasoning}"
1566+
f"Message: {safe_message} | Complex: {is_complex_query} | Reasoning: {enable_reasoning}"
15621567
)
15631568
return self._create_fallback_response(message, session_id)
15641569

src/api/routers/mcp.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
from src.api.services.mcp.tool_binding import ToolBindingService
2929
from src.api.services.mcp.tool_routing import ToolRoutingService, RoutingStrategy
3030
from src.api.services.mcp.tool_validation import ToolValidationService
31+
from src.api.utils.log_utils import sanitize_log_data
32+
from src.api.utils.error_handler import sanitize_error_message
3133

3234
logger = logging.getLogger(__name__)
3335

@@ -230,8 +232,12 @@ async def execute_tool(tool_id: str, parameters: Dict[str, Any] = None):
230232
"status": "success",
231233
}
232234
except Exception as e:
233-
logger.error(f"Error executing tool {tool_id}: {e}")
234-
raise HTTPException(status_code=500, detail=f"Failed to execute tool: {str(e)}")
235+
# Sanitize user-controlled data before logging
236+
safe_tool_id = sanitize_log_data(tool_id, max_length=100)
237+
logger.error(f"Error executing tool {safe_tool_id}: {sanitize_log_data(str(e))}")
238+
# Use sanitized error message for HTTP response
239+
error_msg = sanitize_error_message(e, "Tool execution")
240+
raise HTTPException(status_code=500, detail=error_msg)
235241

236242

237243
@router.post("/test-workflow")
@@ -253,10 +259,12 @@ async def test_mcp_workflow(message: str, session_id: str = "test"):
253259
"status": "success",
254260
}
255261
except Exception as e:
256-
logger.error(f"Error testing MCP workflow: {e}")
257-
raise HTTPException(
258-
status_code=500, detail=f"Failed to test MCP workflow: {str(e)}"
259-
)
262+
# Sanitize user-controlled data before logging
263+
safe_message = sanitize_log_data(message, max_length=200)
264+
logger.error(f"Error testing MCP workflow: {sanitize_log_data(str(e))}")
265+
# Use sanitized error message for HTTP response
266+
error_msg = sanitize_error_message(e, "MCP workflow testing")
267+
raise HTTPException(status_code=500, detail=error_msg)
260268

261269

262270
@router.get("/agents")

0 commit comments

Comments
 (0)