mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-11 09:44:44 +08:00
* security: add log injection attack prevention with input sanitization - Created src/utils/log_sanitizer.py to sanitize user-controlled input before logging - Prevents log injection attacks using newlines, tabs, carriage returns, etc. - Escapes dangerous characters: \n, \r, \t, \0, \x1b - Provides specialized functions for different input types: - sanitize_log_input: general purpose sanitization - sanitize_thread_id: for user-provided thread IDs - sanitize_user_content: for user messages (more aggressive truncation) - sanitize_agent_name: for agent identifiers - sanitize_tool_name: for tool names - sanitize_feedback: for user interrupt feedback - create_safe_log_message: template-based safe message creation - Updated src/server/app.py to sanitize all user input in logging: - Thread IDs from request parameter - Message content from user - Agent names and node information - Tool names and feedback - Updated src/agents/tool_interceptor.py to sanitize: - Tool names during execution - User feedback during interrupt handling - Tool input data - Added 29 comprehensive unit tests covering: - Classic newline injection attacks - Carriage return injection - Tab and null character injection - HTML/ANSI escape sequence injection - Combined multi-character attacks - Truncation and length limits Fixes potential log forgery vulnerability where malicious users could inject fake log entries via unsanitized input containing control characters.
78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import logging
|
|
from typing import List, Optional
|
|
|
|
from langgraph.prebuilt import create_react_agent
|
|
|
|
from src.agents.tool_interceptor import wrap_tools_with_interceptor
|
|
from src.config.agents import AGENT_LLM_MAP
|
|
from src.llms.llm import get_llm_by_type
|
|
from src.prompts import apply_prompt_template
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# Create agents using configured LLM types
|
|
def create_agent(
|
|
agent_name: str,
|
|
agent_type: str,
|
|
tools: list,
|
|
prompt_template: str,
|
|
pre_model_hook: callable = None,
|
|
interrupt_before_tools: Optional[List[str]] = None,
|
|
):
|
|
"""Factory function to create agents with consistent configuration.
|
|
|
|
Args:
|
|
agent_name: Name of the agent
|
|
agent_type: Type of agent (researcher, coder, etc.)
|
|
tools: List of tools available to the agent
|
|
prompt_template: Name of the prompt template to use
|
|
pre_model_hook: Optional hook to preprocess state before model invocation
|
|
interrupt_before_tools: Optional list of tool names to interrupt before execution
|
|
|
|
Returns:
|
|
A configured agent graph
|
|
"""
|
|
logger.debug(
|
|
f"Creating agent '{agent_name}' of type '{agent_type}' "
|
|
f"with {len(tools)} tools and template '{prompt_template}'"
|
|
)
|
|
|
|
# Wrap tools with interrupt logic if specified
|
|
processed_tools = tools
|
|
if interrupt_before_tools:
|
|
logger.info(
|
|
f"Creating agent '{agent_name}' with tool-specific interrupts: {interrupt_before_tools}"
|
|
)
|
|
logger.debug(f"Wrapping {len(tools)} tools for agent '{agent_name}'")
|
|
processed_tools = wrap_tools_with_interceptor(tools, interrupt_before_tools)
|
|
logger.debug(f"Agent '{agent_name}' tool wrapping completed")
|
|
else:
|
|
logger.debug(f"Agent '{agent_name}' has no interrupt-before-tools configured")
|
|
|
|
if agent_type not in AGENT_LLM_MAP:
|
|
logger.warning(
|
|
f"Agent type '{agent_type}' not found in AGENT_LLM_MAP. "
|
|
f"Falling back to default LLM type 'basic' for agent '{agent_name}'. "
|
|
"This may indicate a configuration issue."
|
|
)
|
|
llm_type = AGENT_LLM_MAP.get(agent_type, "basic")
|
|
logger.debug(f"Agent '{agent_name}' using LLM type: {llm_type}")
|
|
|
|
logger.debug(f"Creating ReAct agent '{agent_name}'")
|
|
agent = create_react_agent(
|
|
name=agent_name,
|
|
model=get_llm_by_type(llm_type),
|
|
tools=processed_tools,
|
|
prompt=lambda state: apply_prompt_template(
|
|
prompt_template, state, locale=state.get("locale", "en-US")
|
|
),
|
|
pre_model_hook=pre_model_hook,
|
|
)
|
|
logger.info(f"Agent '{agent_name}' created successfully")
|
|
|
|
return agent
|