refactor(agent): 重构Agent架构并实现动态Agent树

feat(sandbox): 增强沙箱工具的错误处理和日志记录
test(verification): 添加沙箱验证工具的独立测试脚本
docs: 删除过时的文档和测试文件
This commit is contained in:
lintsinghua 2025-12-14 14:52:06 +08:00
parent e29231cc73
commit a85cdb687d
10 changed files with 248 additions and 1309 deletions

View File

@ -1,93 +0,0 @@
# 使用 uv 管理 Python 依赖
本项目已迁移到使用 [uv](https://github.com/astral-sh/uv) 作为 Python 依赖管理器。
## 快速开始
### 安装 uv
```bash
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# 或使用 Homebrew
brew install uv
```
### 安装依赖
```bash
cd backend
uv sync
```
这会自动创建虚拟环境并安装所有依赖。
### 运行项目
```bash
# 激活虚拟环境uv 会自动管理)
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
# 或使用 uv 直接运行
uv run python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
### 数据库迁移
```bash
uv run alembic upgrade head
```
### 添加新依赖
```bash
# 添加依赖
uv add package-name
# 添加开发依赖
uv add --dev package-name
```
### 更新依赖
```bash
uv sync --upgrade
```
### 其他常用命令
```bash
# 查看已安装的包
uv pip list
# 运行 Python 脚本
uv run python script.py
# 运行 Alembic 命令
uv run alembic <command>
```
## 从 pip/venv 迁移
如果你之前使用 pip 和 venv
1. 删除旧的虚拟环境(可选):
```bash
rm -rf venv
```
2. 使用 uv 同步依赖:
```bash
uv sync
```
3. 之后使用 `uv run` 运行命令,或激活 uv 创建的虚拟环境。
## 优势
- **速度快**:比 pip 快 10-100 倍
- **可复现**:自动生成锁文件
- **简单**:一个命令管理所有依赖
- **兼容**:完全兼容 pip 和 requirements.txt

View File

@ -1,82 +0,0 @@
# 迁移到 uv 依赖管理器
## ✅ 已完成的工作
1. **初始化 uv 项目**
- 创建了 `pyproject.toml` 配置文件
- 所有依赖已迁移到 `pyproject.toml`
2. **依赖管理**
- 使用 `uv sync` 安装所有依赖
- 创建了 `.venv` 虚拟环境uv 自动管理)
- 生成了 `requirements-lock.txt` 锁定文件
3. **工具和脚本**
- 创建了 `start.sh` 启动脚本
- 创建了 `README_UV.md` 使用文档
## 📝 使用方式
### 启动服务
```bash
cd backend
./start.sh
```
或手动启动:
```bash
cd backend
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
### 数据库迁移
```bash
cd backend
uv run alembic upgrade head
```
### 添加新依赖
```bash
cd backend
uv add package-name
```
## 🔄 从旧环境迁移
如果你之前使用 `venv``pip`
1. **删除旧虚拟环境**(可选):
```bash
rm -rf venv
```
2. **使用 uv 同步**
```bash
uv sync
```
3. **之后使用 `uv run` 运行所有命令**
## 📦 依赖文件说明
- `pyproject.toml` - 项目配置和依赖声明(主要文件)
- `requirements.txt` - 保留用于兼容性,但建议使用 `pyproject.toml`
- `requirements-lock.txt` - 自动生成的锁定文件(确保可复现)
## ⚠️ 注意事项
- uv 创建的虚拟环境在 `.venv/` 目录(不是 `venv/`
- 使用 `uv run` 运行命令会自动使用正确的虚拟环境
- 也可以手动激活:`source .venv/bin/activate`
## 🎯 优势
- ⚡ **速度快**:比 pip 快 10-100 倍
- 🔒 **可复现**:自动生成锁定文件
- 🎯 **简单**:一个命令管理所有依赖
- 🔄 **兼容**:完全兼容 pip 和 requirements.txt

View File

@ -271,6 +271,7 @@ class AgentRunner:
}
# 沙箱工具(仅 Verification Agent 可用)
self.sandbox_manager = None
try:
from app.services.agent.tools.sandbox_tool import SandboxConfig
sandbox_config = SandboxConfig(
@ -281,17 +282,27 @@ class AgentRunner:
network_mode=settings.SANDBOX_NETWORK_MODE,
)
self.sandbox_manager = SandboxManager(config=sandbox_config)
except Exception as e:
logger.warning(f"❌ Sandbox Manager initialization failed: {e}")
import traceback
logger.warning(f"Traceback: {traceback.format_exc()}")
# 尝试创建默认管理器作为后备
try:
self.sandbox_manager = SandboxManager()
logger.info("⚠️ Created fallback SandboxManager (Docker might be unavailable)")
except Exception as e2:
logger.error(f"❌ Failed to create fallback SandboxManager: {e2}")
# 始终注册沙箱工具,即使 Docker 不可用(工具内部会检查)
if self.sandbox_manager:
self.verification_tools["sandbox_exec"] = SandboxTool(self.sandbox_manager)
self.verification_tools["sandbox_http"] = SandboxHttpTool(self.sandbox_manager)
self.verification_tools["verify_vulnerability"] = VulnerabilityVerifyTool(self.sandbox_manager)
logger.info(f"✅ Sandbox tools initialized successfully: sandbox_exec, sandbox_http, verify_vulnerability")
logger.info(f"✅ Verification tools: {list(self.verification_tools.keys())}")
logger.info(f"✅ Sandbox tools initialized (Docker available: {self.sandbox_manager.is_available})")
else:
logger.error("❌ Sandbox tools NOT initialized due to critical manager failure")
except Exception as e:
logger.warning(f"❌ Sandbox initialization failed: {e}")
import traceback
logger.warning(f"Traceback: {traceback.format_exc()}")
logger.info(f"✅ Verification tools: {list(self.verification_tools.keys())}")
# 统计总工具数
total_tools = len(set(

View File

@ -614,12 +614,15 @@ class SandboxHttpTool(AgentTool):
**kwargs
) -> ToolResult:
"""执行 HTTP 请求"""
try:
await self.sandbox_manager.initialize()
except Exception as e:
logger.warning(f"Sandbox init failed during execution: {e}")
if not self.sandbox_manager.is_available:
return ToolResult(
success=False,
error="沙箱环境不可用",
error="沙箱环境不可用 (Docker Unavailable)",
)
result = await self.sandbox_manager.execute_http_request(
@ -716,12 +719,15 @@ class VulnerabilityVerifyTool(AgentTool):
**kwargs
) -> ToolResult:
"""执行漏洞验证"""
try:
await self.sandbox_manager.initialize()
except Exception as e:
logger.warning(f"Sandbox init failed during execution: {e}")
if not self.sandbox_manager.is_available:
return ToolResult(
success=False,
error="沙箱环境不可用",
error="沙箱环境不可用 (Docker Unavailable)",
)
result = await self.sandbox_manager.verify_vulnerability(

View File

@ -8,7 +8,7 @@ import re
import logging
from typing import Dict, Any, Optional, List
from .types import LLMConfig, LLMProvider, LLMMessage, LLMRequest, DEFAULT_MODELS
from .factory import LLMFactory
from .factory import LLMFactory, NATIVE_ONLY_PROVIDERS
from app.core.config import settings
# json-repair 库用于修复损坏的 JSON
@ -460,8 +460,6 @@ Please analyze the following code:
Yields:
dict: {"type": "token", "content": str} {"type": "done", ...}
"""
from .adapters.litellm_adapter import LiteLLMAdapter
llm_messages = [
LLMMessage(role=msg["role"], content=msg["content"])
for msg in messages
@ -473,9 +471,44 @@ Please analyze the following code:
max_tokens=max_tokens,
)
# 使用 LiteLLM adapter 进行流式调用
if self.config.provider in NATIVE_ONLY_PROVIDERS:
adapter = LLMFactory.create_adapter(self.config)
response = await adapter.complete(request)
content = response.content or ""
usage = None
if response.usage:
usage = {
"prompt_tokens": response.usage.prompt_tokens or 0,
"completion_tokens": response.usage.completion_tokens or 0,
"total_tokens": response.usage.total_tokens or 0,
}
if not content:
yield {
"type": "done",
"content": "",
"usage": usage,
"finish_reason": response.finish_reason or "stop",
}
else:
accumulated = ""
chunk_size = 20
for i in range(0, len(content), chunk_size):
part = content[i:i + chunk_size]
accumulated += part
yield {
"type": "token",
"content": part,
"accumulated": accumulated,
}
yield {
"type": "done",
"content": content,
"usage": usage,
"finish_reason": response.finish_reason or "stop",
}
else:
from .adapters.litellm_adapter import LiteLLMAdapter
adapter = LiteLLMAdapter(self.config)
async for chunk in adapter.stream_complete(request):
yield chunk

View File

@ -0,0 +1,179 @@
import asyncio
import os
import sys
import json
import logging
from typing import Dict, Any, List
# Add backend to path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from app.db.session import AsyncSessionLocal
from app.models.user_config import UserConfig
from app.services.llm.service import LLMService
from app.services.agent.agents.verification import VerificationAgent
from app.services.agent.tools.sandbox_tool import SandboxTool, SandboxHttpTool, VulnerabilityVerifyTool, SandboxManager, SandboxConfig
from app.services.agent.agents.base import AgentType
from app.services.agent.config import AgentConfig
from app.core.config import settings
from sqlalchemy import select
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
async def get_user_llm_config():
"""Fetch LLM configuration from the first user in the database"""
async with AsyncSessionLocal() as session:
result = await session.execute(select(UserConfig))
user_config = result.scalars().first()
if not user_config:
logger.error("❌ No user config found in database!")
return None
logger.info(f"✅ Loaded config for user_id: {user_config.user_id}")
import json
raw_config = user_config.llm_config
llm_data = json.loads(raw_config) if raw_config else {}
logger.info(f"📂 Loaded LLM config keys: {list(llm_data.keys())}")
# Try to find keys regardless of naming convention (camelCase vs snake_case)
api_key = llm_data.get("api_key") or llm_data.get("llmApiKey") or llm_data.get("apiKey")
base_url = llm_data.get("base_url") or llm_data.get("llmBaseUrl") or llm_data.get("baseUrl")
model = llm_data.get("model") or llm_data.get("llmModel")
provider = llm_data.get("provider") or llm_data.get("llmProvider")
return {
"api_key": api_key,
"base_url": base_url,
"model": model,
"provider": provider
}
async def run_verification_test():
print("\n🚀 Starting Verification Agent Sandbox Test (Standalone Mode)\n")
llm_config = await get_user_llm_config()
if not llm_config:
return
override_provider = os.getenv("TEST_LLM_PROVIDER")
override_api_key = os.getenv("TEST_LLM_API_KEY")
override_model = os.getenv("TEST_LLM_MODEL")
if override_provider or override_api_key or override_model:
llm_config["provider"] = override_provider or llm_config.get("provider")
llm_config["api_key"] = override_api_key or llm_config.get("api_key")
llm_config["model"] = override_model or llm_config.get("model")
# 2. Initialize LLM Service
# Transform simple config to the structure LLMService expects
service_user_config = {
"llmConfig": {
"llmProvider": llm_config.get("provider"),
"llmApiKey": llm_config.get("api_key"),
"llmModel": llm_config.get("model"),
"llmBaseUrl": llm_config.get("base_url")
}
}
llm_service = LLMService(user_config=service_user_config)
# Also update settings just in case
if llm_config.get("api_key"):
settings.LLM_API_KEY = llm_config["api_key"]
print(f"🔧 Configured LLM: {llm_config.get('provider')} / {llm_config.get('model')}")
# 3. Initialize Sandbox Tools
print("📦 Initializing Sandbox Tools...")
try:
sandbox_config = SandboxConfig(
image=settings.SANDBOX_IMAGE,
memory_limit=settings.SANDBOX_MEMORY_LIMIT,
cpu_limit=settings.SANDBOX_CPU_LIMIT,
timeout=settings.SANDBOX_TIMEOUT,
network_mode=settings.SANDBOX_NETWORK_MODE,
)
sandbox_manager = SandboxManager(config=sandbox_config)
# Pre-check docker
await sandbox_manager.initialize()
if sandbox_manager.is_available:
print("✅ Docker Sandbox is AVAILABLE")
else:
print("⚠️ Docker Sandbox is UNAVAILABLE (Tools will return error messages)")
tools = {
"sandbox_exec": SandboxTool(sandbox_manager),
"sandbox_http": SandboxHttpTool(sandbox_manager),
"verify_vulnerability": VulnerabilityVerifyTool(sandbox_manager)
}
except Exception as e:
print(f"❌ Failed to init sandbox: {e}")
return
# 4. Initialize Verification Agent
# VerificationAgent.__init__ does not take 'config' argument, it builds it internally.
agent = VerificationAgent(
llm_service=llm_service,
tools=tools
)
# 5. Create Mock Input (Simulating a Command Injection Finding)
mock_findings = [
{
"id": "finding_123",
"type": "command_injection",
"file": "legacy/vuln.php",
"line": 42,
"code": "<?php system($_GET['cmd']); ?>",
"confidence": "high",
"severity": "critical",
"description": "User input is directly passed to system() function.",
"context": "Legacy admin panel file."
}
]
input_data = {
"previous_results": {
"findings": mock_findings
},
"task": "Verify this critical command injection vulnerability using sandbox tools.",
}
print("\n🎯 Starting Verification Task...")
print(f"Input: {json.dumps(input_data, indent=2, ensure_ascii=False)}")
print("-" * 50)
# 6. Run Agent
try:
result = await agent.run(input_data)
print("\n✅ Verification Completed!")
print("-" * 50)
if hasattr(result, "model_dump"):
print(json.dumps(result.model_dump(), indent=2, ensure_ascii=False))
elif hasattr(result, "__dict__"):
print(json.dumps(result.__dict__, indent=2, ensure_ascii=False, default=str))
else:
print(str(result))
stats = agent.get_stats()
print(f"\n📊 Stats: Tool Calls={stats['tool_calls']}, Tokens={stats['tokens_used']}")
if stats.get("tool_calls", 0) == 0:
print("\n⚠️ LLM 未调用任何工具,直接通过 VerificationAgent.execute_tool 测试 sandbox_exec...")
observation = await agent.execute_tool(
"sandbox_exec",
{"command": "echo sandbox_test", "timeout": 10}
)
print("\n🔍 Direct sandbox_exec result:")
print(observation)
except Exception as e:
print(f"\n❌ Execution Failed: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(run_verification_test())

View File

@ -1,32 +0,0 @@
import os
import base64
def test_logo_read():
try:
# 模拟 ReportGenerator 中的路径逻辑
current_dir = os.getcwd() # 假设我们在 backend 目录下运行
# 调整逻辑以匹配 ReportGenerator.__file__ 的行为
# 假设脚本在 backend/app/services/test_logo.py
# 直接使用绝对路径进行测试,排除相对路径计算干扰
project_root = "/Users/lintsinghua/DeepAudit"
logo_path = os.path.join(project_root, 'frontend/public/logo_deepaudit.png')
print(f"Looking for logo at: {logo_path}")
if os.path.exists(logo_path):
print("File exists.")
with open(logo_path, "rb") as image_file:
data = image_file.read()
b64 = base64.b64encode(data).decode('utf-8')
print(f"Read {len(data)} bytes.")
print(f"Base64 length: {len(b64)}")
print(f"Base64 prefix: {b64[:50]}...")
else:
print("File does NOT exist.")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
test_logo_read()

View File

@ -1,297 +0,0 @@
前端页面情况:
16:18:28
🔗 Connected to audit stream
16:18:43
Orchestrator
Thought: 我需要首先了解这个项目的整体结构和功能以便确定审计的重点。从目录结构来看这是一个复杂的多模块系统包含多个引擎MediaEngine, MindSpider, QueryEngine等和相关的报告系统。我应该先使用recon Agent来分析项目结构、技术栈和入口点以便后续有针对性地进行安全审计。
16:18:49
📤 调度 recon Agent: 分析项目整体结构、技术栈、入口点和主要功能模块...
Orchestrator
16:18:57
Recon
Thought: 用户指定了审计范围是1个目标文件InsightEngine/llms/__init__.py。我需要直接读取和分析这个文件不要浪费时间遍历其他目录。首先我应该读取这个文件的内容来了解其结构和功能。
16:19:00
Completed: read_file
Recon
0ms
16:19:10
Recon
Thought: 我已经读取了指定的文件 InsightEngine/llms/__init__.py。这是一个简单的Python模块初始化文件它从.base模块导入了LLMClient类。为了更好地理解这个模块的上下文和依赖关系我应该搜索项目中是否有其他相关的文件特别是base.py文件以及可能使用LLMClient的其他文件。
16:19:13
Completed: search_code
Recon
13ms
16:19:15
Recon
Thought: 搜索结果显示LLMClient只在InsightEngine/llms/__init__.py文件中被引用。为了更全面地了解这个模块我应该查找base.py文件因为它是LLMClient的定义所在。同时我也应该搜索项目中是否有其他使用这个LLMClient的文件以了解它的使用场景。
16:19:17
Completed: search_code
Recon
6ms
16:19:19
Recon
Thought: 搜索base.py没有找到结果。让我尝试搜索"from .base"或"import base"来找到base模块的定义位置。同时我也应该搜索整个项目中是否有其他文件引用了InsightEngine.llms或LLMClient以了解这个模块的使用范围。
16:19:21
Completed: search_code
Recon
6ms
16:19:23
Recon
Thought: 看来base.py文件可能不在审计范围内或者它可能是一个不存在的文件。让我尝试搜索"InsightEngine"来了解这个模块在整个项目中的使用情况以及是否有其他相关的LLM或大语言模型相关的文件。
16:19:25
Completed: search_code
Recon
8ms
16:19:48
Recon
Thought: 看起来搜索范围仅限于用户指定的单个文件。根据用户的要求审计范围限定为1个目标文件InsightEngine/llms/__init__.py。这意味着我只能分析这个文件而不能访问项目中的其他文件。
让我总结一下从这个文件中收集到的信息:
1. 这是一个名为LLM的模块为Insight Engine提供统一的OpenAI兼容客户端
2. 它从.base模块导入了LLMClient类
3. 它通过__all__列表暴露了LLMClient类
由于base.py文件不在审计范围内我无法获取LLMClient的具体实现。但根据文件描述这个模块似乎是一个大语言模型(LLM)客户端可能与OpenAI API兼容。
16:19:58
Completed: reflect
Recon
0ms
16:19:59
Recon
Thought: 我已经完成了对指定文件的分析。由于审计范围被限定为单个文件,我无法获取更多关于项目结构、技术栈、入口点等信息。我现在可以总结收集到的信息并输出最终结果。
Final Answer:
```json
{
"project_structure": {
"directories": [],
"config_files": [],
"total_files": 1
},
"tech_stack": {
"languages": ["Python"],
"frameworks": [],
"databases": []
},
"entry_points": [
{"type": "module_init", "file": "InsightEngine/llms/__init__.py", "line": 6}
],
"high_risk_areas": [],
"dependencies": {
"internal": ["base.LLMClient"],
"external": []
},
"initial_findings": []
}
```
16:20:05
✅ recon Agent 完成
Orchestrator
16:20:07
Orchestrator
Thought: Recon Agent的结果显示只分析了1个文件这与项目目录结构中显示的多个目录和文件不符。这可能是因为Recon Agent没有正确扫描整个项目结构。我需要重新调度Recon Agent或者直接转向Analysis Agent进行更深入的分析。考虑到项目结构复杂包含多个引擎模块我应该尝试让Analysis Agent直接对整个项目进行安全审计重点关注用户指定的漏洞类型SQL注入、XSS、命令注入、路径遍历和SSRF。
16:20:15
📤 调度 analysis Agent: 对整个项目进行安全审计重点关注SQL注入、XSS、命令注入、路径遍历和SSRF漏洞...
Orchestrator
16:20:18
Analysis
Thought: 我需要分析指定的文件 InsightEngine/llms/__init__.py。首先我应该读取这个文件的内容了解其结构和功能然后根据代码内容选择合适的分析工具来检测潜在的安全漏洞。
16:20:21
Completed: read_file
Analysis
1ms
16:20:23
Analysis
Thought: 这个文件是一个简单的Python模块初始化文件它只导入了`LLMClient`类并定义了`__all__`列表。文件本身非常短,没有明显的安全漏洞。但是,为了全面分析,我需要查看被导入的`base.py`文件,因为实际的实现逻辑可能在那里。我应该继续读取`base.py`文件来进行更深入的安全分析。
16:20:25
Completed: read_file
Analysis
0ms
16:20:43
Analysis
Thought: 我只能分析用户指定的文件,即 InsightEngine/llms/__init__.py。这个文件本身非常简单只包含导入语句和模块定义没有明显的安全漏洞。由于文件内容非常有限我可以使用 pattern_match 工具来进一步确认是否存在任何潜在的安全模式,尽管从目前来看,这个文件几乎不可能包含安全漏洞。
16:20:49
Completed: pattern_match
Analysis
5ms
16:21:41
Analysis
Thought: 我已经完成了对 InsightEngine/llms/__init__.py 文件的分析。这个文件是一个简单的Python模块初始化文件只包含导入语句和模块定义没有包含任何可能存在安全漏洞的代码。pattern_match 工具也没有检测到任何已知的危险模式。由于这个文件非常简单且只包含导入语句,它本身不会构成安全风险。我应该总结分析结果。
16:21:48
Completed: reflect
Analysis
0ms
16:21:50
Analysis
Thought: 我已经完成了对 InsightEngine/llms/__init__.py 文件的全面安全分析。这个文件非常简单只包含导入语句和模块定义没有包含任何可能存在安全漏洞的代码。pattern_match 工具也没有检测到任何已知的危险模式。由于这个文件本身不包含任何业务逻辑或敏感操作,它不会构成安全风险。现在我可以提供最终的分析结果。
Final Answer: {
"findings": [],
"summary": "已完成对 InsightEngine/llms/__init__.py 文件的安全分析。该文件是一个简单的Python模块初始化文件只包含导入语句和模块定义没有包含任何可能存在安全漏洞的代码。pattern_match 工具也没有检测到任何已知的危险模式。由于这个文件本身不包含任何业务逻辑或敏感操作,它不会构成安全风险。"
}
16:22:00
Analysis
```json
{
"findings": [],
"summary": "已完成对 InsightEngine/llms/__init__.py 文件的安全分析。该文件是一个简单的Python模块初始化文件只包含导入语句和模块定义没有包含任何可能存在安全漏洞的代码。pattern_match 工具也没有检测到任何已知的危险模式。由于这个文件本身不包含任何业务逻辑或敏感操作,它不会构成安全风险。"
}
```
16:22:04
✅ analysis Agent 完成
Orchestrator
16:22:05
Orchestrator
Thought: Analysis Agent也没有发现任何漏洞这很奇怪因为项目结构复杂且包含多个模块。可能是因为Agent没有正确访问到所有文件。让我尝试直接查看一些关键文件特别是入口点文件如app.py和report_engine_only.py这些通常是用户交互的主要入口点可能包含安全漏洞。
16:22:11
📤 调度 recon Agent: 重新分析项目,重点关注入口点文件和主要模块...
Orchestrator
16:22:18
Recon
Thought: 我需要收集项目信息但审计范围限定为1个目标文件InsightEngine/llms/__init__.py。用户还提到之前的分析可能没有正确访问到所有文件需要关注app.py、report_engine_only.py等入口点文件。我应该先读取指定的目标文件然后探索项目结构以获取更全面的信息。
16:22:22
Completed: read_file
Recon
1ms
16:22:23
Recon
Thought: 我已经读取了指定的目标文件 InsightEngine/llms/__init__.py这是一个简单的模块初始化文件它从 .base 导入了 LLMClient 类。现在我需要探索项目结构,了解整个项目的组织方式,特别是用户提到的 app.py、report_engine_only.py 等入口点文件。我将列出根目录的内容来获取项目结构。
16:22:28
Completed: list_files
Recon
18ms
16:23:05
Recon
Thought: 系统显示审计范围限定为1个指定文件但我注意到用户在任务上下文中特别提到了需要关注app.py、report_engine_only.py等入口点文件。我应该尝试搜索这些关键文件看看它们是否存在于项目中。我将先搜索app.py文件。
16:23:08
Completed: search_code
Recon
17ms
16:23:11
Recon
Thought: 没有找到app.py文件。让我尝试搜索report_engine_only.py文件看看它是否存在。
16:23:12
Completed: search_code
Recon
9ms
16:23:43
Recon
Thought: 看来系统中确实只有指定的1个文件。让我尝试搜索其他可能的入口点文件比如main.py或index.py看看是否有其他入口点。
16:23:46
Completed: search_code
Recon
19ms
16:23:47
Recon
Thought: 系统中似乎只有指定的1个文件。让我尝试搜索Python文件中常见的入口点模式比如"if __name__ == '__main__'",看看是否有其他入口点代码。
16:23:50
Completed: search_code
Recon
9ms
16:23:54
Recon
Thought: 系统中确实只有指定的1个文件。让我尝试搜索其他可能的关键词比如"Flask"、"Django"等框架相关的关键词,看看是否能推断出技术栈。
16:23:57
Completed: search_code
Recon
9ms
16:23:58
Recon
Thought: 让我尝试搜索其他常见的技术栈关键词,比如"import"语句,看看能收集到什么信息。
16:24:00
Completed: search_code
Recon
9ms
16:24:01
Recon
Thought: 我找到了一个import语句它从.base模块导入了LLMClient。让我尝试搜索其他可能的技术栈关键词比如"from"语句,看看是否有其他导入。
16:24:03
Completed: search_code
Recon
8ms
16:24:19
Recon
Thought: 我已经收集了足够的信息。系统中只有指定的1个文件InsightEngine/llms/__init__.py。这是一个简单的模块初始化文件它从.base模块导入了LLMClient类。由于系统中只有这一个文件我无法收集到更多的项目结构、技术栈、入口点等信息。现在我将整理收集到的信息并输出结果。
Final Answer:
```json
{
"project_structure": {
"directories": ["InsightEngine/llms"],
"config_files": [],
"total_files": 1
},
"tech_stack": {
"languages": ["Python"],
"frameworks": [],
"databases": []
},
"entry_points": [
{"type": "module_init", "file": "InsightEngine/llms/__init__.py", "line": 6}
],
"high_risk_areas": [],
"dependencies": {},
"initial_findings": []
}
```
16:24:52
✅ recon Agent 完成
Orchestrator
16:24:54
Orchestrator
Thought: Recon Agent仍然只找到了1个文件这与项目目录结构严重不符。看起来Agent可能无法正确访问项目中的所有文件。考虑到这种情况我应该尝试直接查看一些关键文件的内容特别是app.py和report_engine_only.py这些是项目的主要入口点。我将尝试使用Verification Agent来直接检查这些文件。
16:24:58
📤 调度 verification Agent: 直接检查项目入口点文件app.py和report_engine_only.py的安全问题...
Orchestrator
16:24:58
✅ verification Agent 完成
Orchestrator
16:24:58
Orchestrator
Thought: 所有Agent似乎都无法正确访问项目中的文件这可能是由于项目访问权限或路径问题导致的。根据用户提供的信息我们知道项目包含多个目录和文件但所有Agent都只返回了很少的信息。在这种情况下我应该基于用户提供的信息和目录结构进行推理分析并尝试总结可能的安全风险点。
16:25:11
Orchestrator
Thought: 虽然所有Agent都无法直接访问项目文件进行详细分析但我已经基于项目目录结构进行了推理分析。由于系统限制无法获取更多详细信息我应该结束审计并总结我的发现和建议。
后端日志:
lintsinghua@lintsinghuadeMacBook-Pro backend % uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
INFO: Will watch for changes in these directories: ['/Users/lintsinghua/XCodeReviewer/backend']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [94873] using WatchFiles
INFO: Started server process [94875]
INFO: Waiting for application startup.
INFO:app.main:DeepAudit 后端服务启动中...
INFO:app.db.init_db:开始初始化数据库...
INFO:app.db.init_db:演示账户已存在: demo@example.com
INFO:app.db.init_db:演示数据已存在,跳过创建
INFO:app.services.init_templates:开始初始化系统模板和规则...
INFO:app.services.init_templates:✓ 系统模板和规则初始化完成
INFO:app.db.init_db:数据库初始化完成
INFO:app.main:✓ 数据库初始化完成
INFO:app.main:==================================================
INFO:app.main:DeepAudit 后端服务已启动
INFO:app.main:API 文档: http://localhost:8000/docs
INFO:app.main:==================================================
INFO:app.main:演示账户: demo@example.com / demo123
INFO:app.main:==================================================
INFO: Application startup complete.
[Branch] 项目: d, 类型: github, URL: https://github.com/666ghj/BettaFish
[Branch] GitHub Token: 未配置, GitLab Token: 未配置
[Branch] 警告: GitHub Token 未配置,可能会遇到 API 限制
INFO:httpx:HTTP Request: GET https://api.github.com/repos/666ghj/BettaFish/branches?per_page=100 "HTTP/1.1 200 OK"
[Branch] 成功获取 7 个分支
INFO:httpx:HTTP Request: GET https://api.github.com/repos/666ghj/BettaFish/git/trees/main?recursive=1 "HTTP/1.1 200 OK"
INFO:app.api.v1.endpoints.agent_tasks:Created agent task 8717c2de-fedc-4d39-bb19-6b186da9e610 for project d
INFO:app.api.v1.endpoints.agent_tasks:✅ Cloned repository https://github.com/666ghj/BettaFish (branch: main) to /tmp/deepaudit/8717c2de-fedc-4d39-bb19-6b186da9e610
INFO:app.api.v1.endpoints.agent_tasks:🚀 Task 8717c2de-fedc-4d39-bb19-6b186da9e610 started with Dynamic Agent Tree architecture
WARNING:app.services.agent.agents.recon:[Recon] Empty LLM response in iteration 1
WARNING:app.services.agent.agents.analysis:[Analysis] Empty LLM response in iteration 4
ERROR:app.api.v1.endpoints.agent_tasks:Task 8717c2de-fedc-4d39-bb19-6b186da9e610 failed: property 'progress_percentage' of 'AgentTask' object has no setter
Traceback (most recent call last):
File "/Users/lintsinghua/XCodeReviewer/backend/app/api/v1/endpoints/agent_tasks.py", line 392, in _execute_agent_task
task.progress_percentage = 100.0
^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: property 'progress_percentage' of 'AgentTask' object has no setter
WARNING: WatchFiles detected changes in 'app/services/llm/adapters/litellm_adapter.py'. Reloading...

View File

@ -1,259 +0,0 @@
前端页面输出:
16:36:05
🔗 Connected to audit stream
16:36:35
Orchestrator
Thought: 我需要对这个PHP项目进行安全审计但审计范围已经限定为单个文件(agent_t/1.php)。由于不需要分析整个项目结构我可以直接调度analysis Agent对这个文件进行深度安全审计重点关注用户指定的漏洞类型SQL注入、XSS、命令注入、路径遍历和SSRF。
16:36:44
📤 调度 analysis Agent: 对agent_t/1.php文件进行深度安全审计重点检查sql_injection、xss、command_injection、path_traversal、ssrf等漏洞类型...
Orchestrator
16:36:51
Analysis
Thought: 我需要分析agent_t/1.php文件重点关注SQL注入、XSS、命令注入、路径遍历和SSRF漏洞。首先我应该读取文件内容了解代码结构和逻辑然后使用pattern_match工具进行初步扫描检测常见的不安全模式。
16:36:55
Completed: read_file
Analysis
0ms
16:36:56
Analysis
Thought: 我已经读取了agent_t/1.php文件的内容。这是一个明显包含多种安全漏洞的测试靶场代码。从代码注释可以看出它故意包含了多种漏洞类型包括SQL注入、XSS、命令注入、路径遍历、SSRF等。现在我需要使用pattern_match工具进行系统化的漏洞检测确认这些漏洞并获取详细信息。
16:37:45
Completed: pattern_match
Analysis
3ms
16:37:46
Analysis
Thought: pattern_match工具检测到了2个路径遍历漏洞但我注意到代码中实际上包含更多类型的漏洞。让我使用semgrep_scan工具进行更全面的扫描以检测所有目标漏洞类型包括SQL注入、XSS、命令注入等。
16:37:50
Completed: semgrep_scan
Analysis
100318ms
16:39:31
Analysis
Thought: semgrep工具不可用我需要使用其他方法进行漏洞分析。我已经读取了文件内容可以直接分析代码中的漏洞。从代码中我可以看到多种明显的漏洞包括SQL注入、XSS、命令注入、路径遍历、SSRF等。让我使用dataflow_analysis工具来追踪一些关键的数据流特别是用户输入如何流向危险函数。
16:39:43
Completed: dataflow_analysis
Analysis
79066ms
Input:
{
"source_code": "$username = $_POST['username'];\n$password = $_POST['password'];\n$sql = \"SELECT * FROM users WHERE username = '$username' AND password = '$password'\";\n$result = mysql_query($sql);",
"sink_code": "mysql_query($sql);",
"variable_name": "username",
"file_path": "agent_t/1.php"
}
Output:
null
16:41:04
Analysis
我再尝试分析其他漏洞的数据流特别是命令注入和XSS部分。
16:41:08
Completed: dataflow_analysis
Analysis
63459ms
16:42:14
Analysis
让我尝试分析XSS漏洞的数据流
16:42:18
Completed: dataflow_analysis
Analysis
181539ms
Input:
{
"source_code": "$query = $_GET['q'];\necho \"You searched for: \" . $query;",
"sink_code": "echo \"You searched for: \" . $query;",
"variable_name": "query",
"file_path": "agent_t/1.php"
}
Output:
null
16:45:22
Analysis
Thought: dataflow_analysis工具似乎没有返回有用的结果。不过我已经通过读取文件内容获得了足够的信息来分析漏洞。现在我将总结在agent_t/1.php中发现的所有安全漏洞并按照要求的格式提供最终报告。
从代码分析中,我发现了以下漏洞:
1. SQL注入第34行
2. XSS第77行
3. 命令注入第50行
4. 路径遍历第58行
5. SSRF第66行
6. 硬编码凭证第18行
7. 不安全的反序列化第23行
8. 弱加密算法第39行
9. 敏感信息泄露第80行
10. 任意文件上传第86-87行
11. 越权访问第94行
12. 不安全的随机数生成器第98行
我将按照要求的格式提供最终报告。
Final Answer: ```json
{
"findings": [
{
"vulnerability_type": "sql_injection",
"severity": "high",
"title": "SQL 注入漏洞",
"description": "在登录功能中直接拼接用户输入到SQL查询语句中没有任何过滤或参数化查询导致SQL注入漏洞。",
"file_path": "agent_t/1.php",
"line_start": 34,
"code_snippet": "$sql = \"SELECT * FROM users WHERE username = '$username' AND password = '$password'\";",
"source": "用户输入 (POST username, password)",
"sink": "mysql_query() 函数",
"suggestion": "使用参数化查询或预处理语句避免直接拼接SQL语句。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "xss",
"severity": "high",
"title": "跨站脚本攻击 (XSS)",
"description": "在搜索功能中直接输出用户输入未进行HTML实体编码导致反射型XSS漏洞。",
"file_path": "agent_t/1.php",
"line_start": 77,
"code_snippet": "echo \"You searched for: \" . $query;",
"source": "用户输入 (GET q)",
"sink": "echo 输出函数",
"suggestion": "对输出进行HTML实体编码使用htmlspecialchars()函数。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "command_injection",
"severity": "high",
"title": "命令注入漏洞",
"description": "在ping功能中直接将用户输入传递给shell_exec函数导致命令注入漏洞。",
"file_path": "agent_t/1.php",
"line_start": 50,
"code_snippet": "$cmd = shell_exec(\"ping -c 4 \" . $target);",
"source": "用户输入 (GET ip)",
"sink": "shell_exec() 函数",
"suggestion": "验证和过滤用户输入,使用白名单机制,避免直接执行用户提供的命令。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "path_traversal",
"severity": "high",
"title": "路径遍历漏洞",
"description": "在view功能中直接使用用户提供的文件名进行文件包含操作允许读取服务器上的任意文件。",
"file_path": "agent_t/1.php",
"line_start": 58,
"code_snippet": "include($file);",
"source": "用户输入 (GET file)",
"sink": "include() 函数",
"suggestion": "验证和限制文件路径,使用白名单机制,避免路径遍历字符如../",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "ssrf",
"severity": "high",
"title": "服务端请求伪造 (SSRF)",
"description": "在proxy功能中直接使用用户提供的URL进行文件获取同时禁用了SSL验证导致SSRF漏洞。",
"file_path": "agent_t/1.php",
"line_start": 66,
"code_snippet": "$content = file_get_contents($url, false, stream_context_create([\"ssl\" => [\"verify_peer\"=>false, \"verify_peer_name\"=>false]]));",
"source": "用户输入 (GET url)",
"sink": "file_get_contents() 函数",
"suggestion": "验证和限制URL只允许访问特定域名启用SSL验证使用白名单机制。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "hardcoded_secrets",
"severity": "high",
"title": "硬编码凭证",
"description": "在代码中硬编码了API密钥可能导致凭证泄露。",
"file_path": "agent_t/1.php",
"line_start": 18,
"code_snippet": "$secret_api_key = \"12345-SUPER-SECRET-KEY\";",
"source": "硬编码值",
"sink": "变量存储",
"suggestion": "使用环境变量或安全的配置管理系统存储敏感信息。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "deserialization",
"severity": "high",
"title": "不安全的反序列化",
"description": "直接从Cookie中反序列化用户数据可能导致远程代码执行。",
"file_path": "agent_t/1.php",
"line_start": 23,
"code_snippet": "$pref = unserialize($_COOKIE['user_pref']);",
"source": "用户输入 (Cookie user_pref)",
"sink": "unserialize() 函数",
"suggestion": "避免使用不安全的反序列化使用JSON或其他安全的序列化方法。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "weak_crypto",
"severity": "medium",
"title": "弱加密算法",
"description": "使用MD5算法存储或验证密码MD5已被证明不安全。",
"file_path": "agent_t/1.php",
"line_start": 39,
"code_snippet": "$hash = md5($password);",
"source": "用户输入 (POST password)",
"sink": "md5() 函数",
"suggestion": "使用强哈希算法如bcrypt、Argon2或PBKDF2。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "information_disclosure",
"severity": "medium",
"title": "敏感信息泄露",
"description": "在搜索功能中调用phpinfo()函数,泄露大量服务器信息。",
"file_path": "agent_t/1.php",
"line_start": 80,
"code_snippet": "phpinfo();",
"source": "直接调用",
"sink": "phpinfo() 函数",
"suggestion": "移除phpinfo()调用,在生产环境中禁用错误回显。",
"confidence": 1.0,
"needs_verification": false
},
{
"vulnerability_type": "insecure_random",
"severity": "medium",
"title": "不安全的随机数生成器",
"description": "使用rand()函数生成安全令牌,该函数是可预测的。",
"file_path": "agent_t/1.php",
"line_start": 98,
"code_snippet": "$token = rand(1000, 9999);",
"source": "随机数生成",
"sink": "令牌生成",
"suggestion": "使用random_int()或更安全的随机数生成器。",
"confidence": 1.0,
"needs_verification": false
}
],
"summary": "agent_t/1.php文件是一个包含多种严重安全漏洞的测试靶场代码。文件中存在SQL注入、XSS、命令注入、路径遍历、SSRF等多种高危漏洞以及硬编码凭证、不安全的反序列化、弱加密算法等中危漏洞。这些漏洞组合在一起可能导致完全的系统入侵。建议立即修复所有高危漏洞并重新评估整个应用程序的安全架构。"
}
```
16:47:12
✅ analysis Agent 完成
Orchestrator
16:47:50
Orchestrator
Thought: analysis Agent已经完成了对agent_t/1.php文件的安全审计发现了10个安全问题包括5个高危漏洞和5个中危漏洞。这些漏洞涵盖了用户指定的所有目标漏洞类型SQL注入、XSS、命令注入、路径遍历、SSRF以及其他安全问题。现在我需要调度verification Agent来验证这些发现的漏洞特别是高危漏洞以确保它们是真实存在的。
16:47:53
📤 调度 verification Agent: 验证analysis Agent在agent_t/1.php中发现的安全漏洞特别是高危漏洞SQL注入、XSS、命令注入、路径遍历、SSRF、硬编码凭证、不安全的反序列化以及中危漏洞弱加密算法、...
Orchestrator
16:47:53
✅ verification Agent 完成
Orchestrator
16:47:53
Orchestrator
Thought: verification Agent返回的结果显示没有发现任何漏洞这与analysis Agent的发现形成对比。这可能是因为verification Agent在沙箱环境中无法成功复现漏洞或者验证过程存在问题。考虑到analysis Agent已经详细分析了代码并发现了多个安全问题我应该基于analysis Agent的发现来总结审计结果而不是依赖verification Agent的结果。
16:48:11
Orchestrator
Thought: 我已经完成了对agent_t/1.php文件的安全审计。analysis Agent发现了10个安全问题包括7个高危漏洞和3个中危漏洞涵盖了用户指定的所有目标漏洞类型以及其他安全问题。verification Agent没有返回结果可能是由于沙箱环境的限制。基于analysis Agent的详细分析我现在可以完成审计并提供结论和建议。
16:48:27
✅ Audit completed

View File

@ -1,527 +0,0 @@
DeepAudit Agent 架构重构升级方案
一、现状分析
当前 DeepAudit 架构特点
DeepAudit 目前采用基于 LangGraph 的固定流程图架构。整个审计流程按照 Recon信息收集→ Analysis漏洞分析→ Verification漏洞验证→ Report报告生成的线性顺序执行。每个阶段由一个专门的 Agent 负责Agent 之间通过 TaskHandoff 机制传递结构化的上下文信息。
这种架构的优点是流程清晰、易于理解和调试,但存在几个明显的局限性:
第一,流程过于固定。无论面对什么类型的项目或漏洞,都必须走完整个流程,无法根据实际发现动态调整策略。比如发现了一个 SQL 注入线索,无法立即深入分析,必须等待 Analysis 阶段统一处理。
第二Agent 专业化程度不足。Analysis Agent 需要同时处理所有类型的漏洞,从 SQL 注入到 XSS 到 SSRF这导致系统提示词过于庞大LLM 难以在每种漏洞类型上都表现出专家级水平。
第三缺乏动态协作能力。Agent 之间只能按照预设的顺序传递信息,无法根据需要动态创建新的 Agent 或在 Agent 之间进行实时通信。
Strix 架构的启示
Strix 是一个开源的 AI 安全测试 Agent 项目,它采用了完全不同的架构理念。通过深入分析 Strix 的设计,我们可以获得以下关键启示:
Strix 的核心是动态 Agent 树结构。根 Agent 可以根据任务需要随时创建子 Agent每个子 Agent 专注于特定的漏洞类型或任务。子 Agent 完成后向父 Agent 汇报结果,父 Agent 可以根据结果决定是否需要创建更多子 Agent 或进行其他操作。
Strix 的另一个亮点是模块化的专业知识系统。它为每种漏洞类型都准备了详细的 Jinja2 模板,包含该漏洞的检测方法、利用技术、绕过手段、验证步骤等专业知识。创建 Agent 时可以指定加载哪些知识模块,让 Agent 在特定领域具备专家级能力。
此外Strix 还实现了 Agent 间的消息传递机制、完善的状态管理、工具的沙箱执行、LLM 调用优化等高级特性。
二、升级后的整体架构
核心设计理念
升级后的 DeepAudit 将采用"动态 Agent 协作 + 专业知识模块 + 智能编排"的三层架构。
最底层是专业知识模块层,包含各种漏洞类型、框架、技术栈的专业知识库。这些知识以模板形式存储,可以按需加载到 Agent 的系统提示词中。
中间层是 Agent 执行层,包含可动态创建和销毁的 Agent 实例。每个 Agent 都有完整的生命周期管理,可以执行任务、调用工具、与其他 Agent 通信。
最上层是智能编排层,负责根据审计目标和实时发现来协调整个审计流程,决定何时创建什么类型的 Agent如何分配任务何时结束审计。
动态 Agent 树
与当前固定的四阶段流程不同,升级后的系统将采用动态 Agent 树结构。
审计开始时,系统创建一个根 AgentRoot Agent。根 Agent 首先进行初步的信息收集,了解项目的技术栈、目录结构、入口点等基本信息。然后根据收集到的信息,根 Agent 决定需要创建哪些专业子 Agent。
例如,如果发现项目使用了 SQL 数据库,根 Agent 可能会创建一个专门的 SQL 注入检测 Agent如果发现有用户输入直接渲染到页面的代码可能会创建一个 XSS 检测 Agent如果发现有 HTTP 请求的代码,可能会创建一个 SSRF 检测 Agent。
每个子 Agent 专注于自己的任务领域。当子 Agent 发现可疑的漏洞线索时,它可以进一步创建验证子 Agent 来确认漏洞是否真实存在。验证通过后,还可以创建报告子 Agent 来生成正式的漏洞报告。
这种树状结构的好处是:任务可以无限细分,每个 Agent 都能专注于自己擅长的领域;发现和验证可以并行进行,提高效率;根据实际情况动态调整策略,而不是机械地执行固定流程。
Agent 间通信机制
升级后的系统将实现完善的 Agent 间通信机制。
每个 Agent 都有一个消息队列,其他 Agent 可以向这个队列发送消息。消息类型包括:查询消息(请求信息)、指令消息(要求执行某个操作)、信息消息(分享发现或状态)。
当 Agent 处于等待状态时它会检查自己的消息队列。如果有新消息Agent 会处理消息并可能恢复执行。这种机制使得 Agent 之间可以进行实时协作,而不仅仅是单向的结果传递。
例如SQL 注入检测 Agent 在分析过程中发现某个函数可能存在问题,但需要了解这个函数的调用上下文。它可以向根 Agent 发送查询消息,请求提供相关信息。根 Agent 收到消息后,可以调用代码搜索工具获取信息,然后回复给 SQL 注入检测 Agent。
Agent 状态管理
每个 Agent 都有完整的状态管理,状态信息包括:
基本信息Agent 的唯一标识、名称、父 Agent 标识、创建时间等。
任务信息:当前任务描述、任务上下文、从父 Agent 继承的信息等。
执行状态:当前迭代次数、最大迭代限制、运行状态(运行中、等待中、已完成、失败、已停止)等。
对话历史:与 LLM 的完整对话记录,包括系统提示词、用户消息、助手回复等。
执行记录:已执行的动作列表、观察结果列表、错误记录等。
发现列表:该 Agent 发现的所有漏洞和可疑点。
这种完整的状态管理使得 Agent 可以被暂停和恢复,可以被序列化和持久化,也便于调试和审计。
三、专业知识模块系统
模块化设计
专业知识模块是升级后架构的核心创新之一。我们将为不同的漏洞类型、框架、技术栈创建专门的知识模块。
漏洞类型模块包括SQL 注入、XSS、SSRF、IDOR、认证绕过、远程代码执行、路径遍历、XXE、CSRF、竞态条件、反序列化、业务逻辑漏洞等。每个模块都包含该漏洞类型的完整知识体系。
框架知识模块包括FastAPI、Django、Flask、Express、Next.js、Spring、Laravel 等主流框架。每个模块包含该框架的安全特性、常见漏洞模式、最佳实践等。
技术栈模块包括Supabase、Firebase、GraphQL、gRPC、WebSocket 等。每个模块包含该技术的安全考量和常见问题。
模块内容结构
以 SQL 注入模块为例,它应该包含以下内容:
漏洞概述SQL 注入的定义、危害、影响范围。
检测方法:错误型注入检测、布尔型注入检测、时间型注入检测、带外注入检测的具体技术和判断标准。
数据库特定知识MySQL、PostgreSQL、MSSQL、Oracle 等不同数据库的特有语法、函数、利用技术。
绕过技术WAF 绕过、过滤绕过、编码绕过等高级技术。
ORM 和查询构建器:各种 ORM 框架中容易出现 SQL 注入的 API 和模式。
验证步骤:如何确认漏洞真实存在,如何构造 PoC如何评估影响。
误报识别:哪些情况容易被误判为 SQL 注入,如何排除误报。
修复建议参数化查询、ORM 正确用法、输入验证等修复方案。
模块加载机制
创建 Agent 时,可以指定该 Agent 需要加载哪些知识模块。系统会将这些模块的内容动态注入到 Agent 的系统提示词中。
为了控制提示词长度和保持 Agent 的专注度,每个 Agent 最多加载 5 个知识模块。这个限制迫使我们为每个 Agent 选择最相关的知识,而不是试图让一个 Agent 掌握所有知识。
模块之间可以有依赖关系。例如FastAPI 框架模块可能依赖 Python 安全基础模块GraphQL 模块可能依赖 API 安全基础模块。加载模块时会自动处理这些依赖。
四、工具系统升级
统一的工具注册机制
升级后的工具系统将采用装饰器模式进行统一注册。每个工具都需要提供:工具名称、功能描述、参数定义、返回值说明。
工具按类别组织包括文件操作类读取文件、搜索文件、列出目录、代码分析类模式匹配、数据流分析、AST 分析、外部扫描类Semgrep、Bandit、Gitleaks 等、验证执行类沙箱命令执行、HTTP 请求)、协作类(创建子 Agent、发送消息、等待消息、推理类思考工具、报告类创建漏洞报告
Think 工具
Think 工具是从 Strix 借鉴的关键创新。这是一个让 Agent 进行深度推理的工具Agent 可以用它来:
分析复杂情况当面对复杂的代码逻辑或不确定的漏洞线索时Agent 可以调用 Think 工具进行深入思考。
规划下一步行动:在执行具体操作之前,先用 Think 工具规划策略。
评估发现的严重性:发现可疑点后,用 Think 工具评估其真实性和影响。
决定是否需要创建子 Agent当任务变得复杂时用 Think 工具分析是否需要分解任务。
Think 工具的输出会被记录到 Agent 的对话历史中,帮助 LLM 保持思路的连贯性。
漏洞报告工具
漏洞报告工具是正式记录漏洞的唯一方式。只有通过这个工具创建的漏洞才会被计入最终报告。这个设计确保了漏洞报告的规范性和完整性。
报告工具要求提供完整的漏洞信息漏洞类型、严重程度、标题、详细描述、文件位置、代码片段、PoC、影响分析、修复建议等。
通常只有专门的报告 Agent 才会调用这个工具,确保漏洞在被正式报告之前已经经过了充分的验证。
沙箱执行
涉及代码执行或网络请求的工具都在沙箱环境中运行。沙箱提供资源隔离CPU、内存、网络限制、文件系统隔离、超时控制等安全保障。
沙箱执行通过 Tool Server 机制实现。Agent 发送工具调用请求到 Tool ServerTool Server 在沙箱中执行工具并返回结果。这种设计使得即使工具执行出现问题,也不会影响主系统的稳定性。
五、LLM 调用优化
Prompt Caching
对于支持 Prompt Caching 的 LLM如 Anthropic Claude系统会自动为系统提示词和早期对话添加缓存标记。这样在多轮对话中这些内容只需要处理一次后续调用可以直接使用缓存显著降低 Token 消耗和响应延迟。
缓存策略会根据对话长度动态调整。对于短对话,只缓存系统提示词;对于长对话,会在关键位置添加多个缓存点。
Memory Compression
当对话历史变得很长时,系统会自动进行压缩。压缩策略包括:
移除冗余信息:重复的工具调用结果、过长的代码输出等会被截断或摘要。
合并相似消息:连续的同类型消息可能被合并。
保留关键信息:重要的发现、决策点、错误信息等会被优先保留。
压缩后的对话历史仍然保持语义完整性LLM 可以理解之前发生了什么,但 Token 消耗大大降低。
智能重试
LLM 调用可能因为各种原因失败:网络问题、速率限制、服务不可用等。系统实现了智能重试机制:
对于可重试的错误(如速率限制),会等待适当时间后重试。
对于不可重试的错误(如认证失败),会立即报错并提供清晰的错误信息。
重试时会使用指数退避策略,避免对 LLM 服务造成过大压力。
六、审计流程重构
启动阶段
用户发起审计请求后,系统首先创建根 Agent。根 Agent 加载通用的安全审计知识模块和项目相关的框架知识模块。
根 Agent 的第一个任务是信息收集:扫描项目目录结构、识别技术栈、找出入口点、分析依赖关系。这个阶段类似于当前的 Recon 阶段,但更加灵活。
任务分解阶段
根据信息收集的结果,根 Agent 决定如何分解审计任务。它会考虑:
项目使用了哪些技术?需要创建哪些专业 Agent
有哪些高风险区域?应该优先分析哪些部分?
项目规模如何?需要多少并行 Agent
根 Agent 会创建一批初始的子 Agent每个子 Agent 负责特定的漏洞类型或代码区域。
并行分析阶段
多个子 Agent 并行工作,各自在自己的专业领域进行深入分析。
每个子 Agent 都有自己的工作循环:思考当前状态、选择工具执行、观察结果、决定下一步。这个循环会持续进行,直到 Agent 认为任务完成或达到迭代限制。
子 Agent 在分析过程中可能会发现需要进一步调查的线索。这时它可以创建更专业的子 Agent 来处理,形成多层的 Agent 树。
验证阶段
当分析 Agent 发现可疑的漏洞时,它会创建验证 Agent 来确认漏洞是否真实存在。
验证 Agent 会尝试构造 PoC、进行数据流追踪、在沙箱中测试等。验证通过后验证 Agent 会创建报告 Agent 来生成正式的漏洞报告。
如果验证失败,验证 Agent 会将结果反馈给父 Agent父 Agent 可以决定是否需要进一步调查或将其标记为误报。
汇总阶段
当所有子 Agent 都完成工作后,根 Agent 会汇总所有发现,生成最终的审计报告。
报告包括:发现的所有漏洞(按严重程度排序)、安全评分、技术栈分析、高风险区域标注、修复建议优先级等。
七、可观测性和调试
完整的事件追踪
系统会记录所有重要事件Agent 创建和销毁、工具调用和结果、LLM 请求和响应、Agent 间消息、状态变更等。
这些事件可以实时推送到前端,让用户看到审计的进展。也可以持久化到数据库,用于后续分析和审计。
Agent 树可视化
前端可以展示当前的 Agent 树结构,显示每个 Agent 的状态、任务、发现数量等信息。用户可以点击任何 Agent 查看其详细信息和对话历史。
调试模式
在调试模式下,系统会记录更详细的信息,包括完整的 LLM 提示词和响应、工具执行的详细日志、状态变更的完整历史等。这些信息对于排查问题和优化系统非常有价值。
八、与现有架构的兼容
渐进式迁移
升级不需要一次性完成,可以渐进式进行。
第一步,保持现有的 LangGraph 流程不变,但将 Agent 的状态管理升级为新的模型。
第二步,引入专业知识模块系统,让现有的 Analysis Agent 可以加载不同的知识模块。
第三步,在 Analysis 阶段内部引入子 Agent 机制,允许创建专业的漏洞检测子 Agent。
第四步,逐步放开流程限制,让 Agent 可以更灵活地决定下一步操作。
第五步,完全迁移到动态 Agent 树架构。
保留 LangGraph 的优势
LangGraph 提供了很好的状态管理和检查点机制,这些在新架构中仍然有价值。我们可以将 LangGraph 用于根 Agent 的高层编排,而在子 Agent 层面使用更灵活的动态创建机制。
九、预期收益
更深度的漏洞发现
专业知识模块让每个 Agent 都具备安全专家级别的知识。专注于单一漏洞类型的 Agent 比通用 Agent 更容易发现深层次的问题。
更高的效率
并行的 Agent 执行比串行流程更快。动态任务分解避免了在无关区域浪费时间。
更低的成本
Prompt Caching 和 Memory Compression 显著降低 Token 消耗。专业化的 Agent 使用更短的提示词就能达到更好的效果。
更好的可扩展性
添加新的漏洞类型只需要创建新的知识模块。支持新的框架只需要添加框架知识模块。整个系统的扩展不需要修改核心架构。
更强的可解释性
完整的事件追踪和 Agent 树可视化让用户清楚地了解系统在做什么。Think 工具的输出展示了 Agent 的推理过程。
这个升级方案借鉴了 Strix 的核心设计理念,同时保留了 DeepAudit 的既有优势,通过渐进式迁移降低风险,最终实现一个更强大、更灵活、更专业的安全审计 Agent 系统。
---
## 十、实施进度记录
### 已完成的工作 (2024-12)
#### 1. 核心模块系统 ✅
- `core/state.py`: 增强的Agent状态管理支持完整生命周期
- `core/registry.py`: Agent注册表和动态Agent树管理
- `core/message.py`: Agent间通信机制消息总线
#### 2. 专业知识模块系统 ✅ (基于RAG)
采用模块化文件组织统一使用RAG进行知识检索
```
knowledge/
├── base.py # 基础定义KnowledgeDocument, KnowledgeCategory
├── loader.py # 知识加载器
├── rag_knowledge.py # RAG检索系统
├── tools.py # 知识查询工具
├── vulnerabilities/ # 漏洞类型知识
│ ├── injection.py # SQL注入、NoSQL注入、命令注入、代码注入
│ ├── xss.py # 反射型XSS、存储型XSS、DOM型XSS
│ ├── auth.py # 认证绕过、IDOR、访问控制失效
│ ├── crypto.py # 弱加密、硬编码凭证
│ ├── ssrf.py # SSRF
│ ├── deserialization.py # 不安全的反序列化
│ ├── path_traversal.py # 路径遍历
│ ├── xxe.py # XXE
│ └── race_condition.py # 竞态条件
└── frameworks/ # 框架安全知识
├── fastapi.py # FastAPI安全
├── django.py # Django安全
├── flask.py # Flask安全
├── express.py # Express.js安全
├── react.py # React安全
└── supabase.py # Supabase安全
```
#### 3. Agent基类增强 ✅
- 支持动态Agent树parent_id, 子Agent创建
- Agent间消息通信
- TaskHandoff协作机制
- 知识模块加载
- Memory Compression集成
#### 4. 工具系统 ✅
- `thinking_tool.py`: Think和Reflect工具
- `reporting_tool.py`: 漏洞报告工具
- `agent_tools.py`: Agent协作工具
- CreateSubAgentTool: 动态创建子Agent
- SendMessageTool: Agent间消息发送
- ViewAgentGraphTool: 查看Agent树
- WaitForMessageTool: 等待消息
- AgentFinishTool: 子Agent完成报告
#### 5. LLM调用优化 ✅
- `memory_compressor.py`: 对话历史压缩
- 自动检测是否需要压缩
- 保留关键信息(发现、工具使用、决策、错误)
- 智能摘要生成
- Agent基类集成自动压缩
#### 6. Orchestrator Agent ✅
- LLM驱动的编排决策
- 动态调度子Agent
- ReAct模式执行
### 已完成的工作 (2024-12 续)
#### 7. Prompt Caching ✅
- `llm/prompt_cache.py`: Prompt 缓存管理器
- 支持 Anthropic Claude 的 Prompt Caching
- 动态缓存策略SYSTEM_ONLY, SYSTEM_AND_EARLY, MULTI_POINT
- 缓存统计和效果追踪
- Token 估算工具
- LiteLLM 适配器集成缓存支持
#### 8. 动态Agent树执行器 ✅
- `core/executor.py`: 完整的执行器实现
- `DynamicAgentExecutor`: 动态Agent树执行器
- 并行Agent执行带信号量控制
- 任务依赖管理
- 执行结果汇总
- 超时和取消处理
- `SubAgentExecutor`: 子Agent执行器
- 从父Agent创建和执行子Agent
- 并行子Agent执行
- 结果收集和汇总
- `ExecutionTask`: 执行任务数据结构
- `ExecutionResult`: 执行结果数据结构
#### 9. Agent状态持久化 ✅
- `core/persistence.py`: 持久化模块
- `AgentStatePersistence`: 状态持久化管理器
- 文件系统持久化
- 数据库持久化(可选)
- 检查点列表和清理
- `CheckpointManager`: 检查点管理器
- 自动检查点(按迭代间隔)
- 检查点恢复
- 状态回滚
#### 10. 增强的Agent协作工具 ✅
- `CreateSubAgentTool`: 增强版
- 支持立即执行模式
- 集成SubAgentExecutor
- 上下文传递
- `RunSubAgentsTool`: 批量执行子Agent
- 并行/顺序执行
- 结果汇总
- `CollectSubAgentResultsTool`: 收集子Agent结果
#### 11. 数据库模型扩展 ✅
- `AgentCheckpoint`: Agent检查点模型
- 状态数据存储
- 执行统计
- 检查点类型auto/manual/error/final
- `AgentTreeNode`: Agent树节点模型
- 树结构记录
- 执行状态追踪
- 结果汇总
- Alembic迁移脚本: `007_add_agent_checkpoint_tables.py`
#### 12. API 端点 ✅
- `GET /agent-tasks/{task_id}/agent-tree`: Agent树查询API
- 返回完整的Agent树结构
- 支持运行时内存查询和数据库查询
- 包含执行状态和发现统计
- `GET /agent-tasks/{task_id}/checkpoints`: 检查点列表API
- 支持按Agent ID过滤
- 分页支持
- `GET /agent-tasks/{task_id}/checkpoints/{checkpoint_id}`: 检查点详情API
- 返回完整的Agent状态数据
### 已完成的工作 (2024-12 续2)
#### 13. 前端 Agent 审计页面 ✅ (Strix-inspired Terminal UI)
- `frontend/src/shared/api/agentTasks.ts`: 扩展 API
- `AgentTreeNode`, `AgentTreeResponse` 类型定义
- `AgentCheckpoint`, `CheckpointDetail` 类型定义
- `getAgentTree()`: 获取 Agent 树结构
- `getAgentCheckpoints()`: 获取检查点列表
- `getCheckpointDetail()`: 获取检查点详情
- `frontend/src/pages/AgentAudit.tsx`: 统一的 Agent 审计页面 (参考 Strix TUI 设计)
- **布局**: 左侧活动日志 (75%) + 右侧 Agent 树和统计 (25%)
- **启动画面**: ASCII Art + 动画加载效果
- **活动日志**:
- 实时流式显示 Agent 思考过程
- 工具调用和结果展示
- 漏洞发现高亮
- 自动滚动控制
- 可折叠的日志条目
- **Agent 树可视化**:
- 树状结构展示
- 节点状态图标(运行中/已完成/失败/等待)
- 发现数量徽章
- 节点选择交互
- **实时统计面板**:
- 进度百分比
- 文件分析进度
- Token 使用量
- 发现数量
- 严重程度分布
- **创建任务对话框**: 选择项目后直接跳转到实时流页面
- **任务控制**: 停止/取消任务
- `frontend/src/app/routes.tsx`: 路由配置
- `/agent-audit`: 启动画面 + 创建任务
- `/agent-audit/:taskId`: 任务实时流页面
- `frontend/src/components/layout/Sidebar.tsx`: 侧边栏导航
- 新增 Agent 审计入口图标
### 已完成的工作 (2024-12 续3)
#### 14. 执行架构切换 ✅
- **移除旧的 LangGraph 固定流程架构**
- **启用新的动态 Agent 树架构**
- `backend/app/api/v1/endpoints/agent_tasks.py`:
- `_execute_agent_task()` 重写为使用 `OrchestratorAgent`
- OrchestratorAgent 作为大脑,动态调度子 Agent
- 子 Agent: ReconAgent, AnalysisAgent, VerificationAgent
- 新增辅助函数: `_get_user_config()`, `_initialize_tools()`, `_collect_project_info()`, `_save_findings()`, `_calculate_security_score()`
### 待完成的工作
#### 1. 前端增强
- 知识模块选择 UI创建任务时
- 检查点恢复功能
- 导出报告功能
#### 2. 测试和优化
- 单元测试
- 集成测试
- 性能优化
- 并发执行压力测试
#### 3. 文档
- API文档更新
- 架构图更新
- 使用指南
---
## 十一、架构升级总结
### 已实现的核心功能
1. **Prompt Caching** - 为 Claude 等 LLM 提供缓存支持,减少 Token 消耗
2. **动态 Agent 树执行** - OrchestratorAgent 作为大脑,动态调度子 Agent
3. **Agent 状态持久化** - 文件系统和数据库双重持久化
4. **检查点机制** - 自动检查点、状态恢复、执行历史追踪
5. **增强的协作工具** - 子 Agent 创建、批量执行、结果收集
6. **完整的 API 支持** - Agent 树查询、检查点管理
7. **旧架构已移除** - 不再使用 LangGraph 固定流程,完全切换到动态 Agent 树
### 文件清单
```
backend/app/services/
├── llm/
│ ├── __init__.py # 模块导出
│ ├── prompt_cache.py # 🆕 Prompt Caching
│ ├── memory_compressor.py # Memory Compression
│ └── adapters/
│ └── litellm_adapter.py # 集成 Prompt Caching
├── agent/
│ ├── core/
│ │ ├── __init__.py # 模块导出
│ │ ├── state.py # Agent 状态管理
│ │ ├── registry.py # Agent 注册表
│ │ ├── message.py # Agent 间通信
│ │ ├── executor.py # 🆕 动态 Agent 树执行器
│ │ └── persistence.py # 🆕 状态持久化
│ │
│ ├── tools/
│ │ ├── __init__.py # 模块导出
│ │ ├── agent_tools.py # 🔄 增强的协作工具
│ │ ├── thinking_tool.py # Think/Reflect 工具
│ │ └── reporting_tool.py # 漏洞报告工具
│ │
│ ├── knowledge/ # 专业知识模块
│ │ ├── vulnerabilities/ # 漏洞类型知识
│ │ └── frameworks/ # 框架安全知识
│ │
│ └── agents/
│ ├── base.py # Agent 基类
│ ├── orchestrator.py # 编排 Agent
│ ├── analysis.py # 分析 Agent
│ └── verification.py # 验证 Agent
backend/app/models/
└── agent_task.py # 🔄 新增 AgentCheckpoint, AgentTreeNode
backend/app/api/v1/endpoints/
└── agent_tasks.py # 🔄 新增 Agent 树和检查点 API
backend/alembic/versions/
└── 007_add_agent_checkpoint_tables.py # 🆕 数据库迁移
frontend/src/shared/api/
└── agentTasks.ts # 🔄 扩展 Agent 树和检查点 API
frontend/src/pages/
└── AgentAudit.tsx # 🆕 统一的 Agent 审计页面 (Strix-inspired)
frontend/src/app/
└── routes.tsx # 🔄 新增 Agent 审计路由
frontend/src/components/layout/
└── Sidebar.tsx # 🔄 新增 Agent 审计导航图标
```
### 下一步计划
1. 测试前端页面渲染和流式事件
2. 知识模块选择 UI
3. 检查点恢复功能