灵知系统(ZhiNeng Knowledge System)全面代码审计报告
审计日期: 2026-03-30 审计范围: 全代码库 — 逐文件阅读分析所有 51 个核心源码文件 审计方法: 按依赖层次分 6 批并行读取,每个文件全量分析 已完成的修复阶段: Phase 1-6(路径遍历防护、API密钥保护、DB池统一部分、错误脱敏、LingFlow路径修复、jieba中文分词集成、Redis缓存修复、磁盘清理) 测试基线: 251 passed, 13 failed(均为预存的DB连接问题),零回归
目录
- 系统架构概览
- 🔴 CRITICAL — 必须立即修复
- 🟠 HIGH — 高优先级修复
- 🟡 MEDIUM — 中等优先级
- 🟢 LOW — 代码质量与清理
- LingFlow 启用分析
- 审计发现汇总表
- 修复优先级路线图(Phase 7-12)
1. 系统架构概览
Frontend (Vue) → Nginx:8008 → API:8000 (FastAPI)
├── Middleware: CORS, Security Headers, Rate Limit, GZip, Request Logging
├── Lifespan: ServiceManager → {DatabaseService, CacheService, VectorService, MonitoringService}
├── Auth(已构建但未激活): JWT RS256 + RBAC + AuthMiddleware
├── API v1 路由:
│ ├── /api/v1/documents — CRUD
│ ├── /api/v1/search — 关键词 + 混合 + 提问 + 分类 + 统计
│ ├── /api/v1/health — 健康检查 + 缓存管理
│ ├── /api/v1/gateway — 领域路由 + 指标 + Prometheus
│ ├── /api/v1/reasoning — CoT + ReAct + GraphRAG
│ └── /api/v1/textbook-processing — LingFlow 教材处理
├── 领域: 气功, 中医, 儒家, 通用
├── 网关: Router + Rate Limiter + Circuit Breaker
├── 缓存: L1 (内存) + L2 (Redis)
└── 监控: 健康检查 + 指标 + Prometheus Exporter
代码量统计
| 模块 | 文件数 | 大致行数 | 状态 |
|---|---|---|---|
backend/auth/ |
4 | ~2,685 | ⚠️ 已构建,未启用 |
backend/api/v1/ |
7 | ~1,391 | ✅ 运行中 |
backend/core/ |
7 | ~1,350 | ✅ 运行中 |
backend/services/ |
6 | ~1,545 | ⚠️ 向量搜索为桩代码 |
backend/textbook_processing/ |
3 | ~2,288 | ✅ 路径已修复 |
backend/cache/ |
3 | ~1,560 | ✅ 运行中 |
backend/gateway/ |
3 | ~804 | ✅ 运行中 |
backend/domains/ |
3 | ~500 | ✅ 运行中 |
backend/config/ |
6 | ~756 | ⚠️ 配置冲突 |
backend/monitoring/ |
4 | ~445 | ⚠️ aioredis过时 |
backend/common/ |
2 | ~314 | ⚠️ SQL注入风险 |
| 总计 | ~51 | ~14,000+ |
已读取的全部文件清单
展开查看完整文件列表(51个文件,全部逐行审计)
**Batch 1 — Config 系统 (756行)** - `backend/config/__init__.py` (163行) - `backend/config/base.py` (114行) - `backend/config/database.py` (135行) - `backend/config/redis.py` (103行) - `backend/config/security.py` (126行) - `backend/config/lingzhi.py` (115行) **Batch 2 — API路由层 (1,391行)** - `backend/api/v1/__init__.py` (21行) - `backend/api/v1/documents.py` (93行) - `backend/api/v1/search.py` (226行) - `backend/api/v1/health.py` (212行) - `backend/api/v1/gateway.py` (255行) - `backend/api/v1/reasoning.py` (289行) - `backend/api/v1/textbook_processing.py` (295行) **Batch 3 — 业务逻辑 (3,584行)** - `backend/services/retrieval/vector.py` (263行) - `backend/services/retrieval/hybrid.py` (201行) - `backend/services/retrieval/bm25.py` (236行) - `backend/services/textbook_service.py` (306行) - `backend/services/compression.py` (528行) - `backend/textbook_processing/autonomous_processor.py` (962行) - `backend/textbook_processing/workflow.py` (808行) - `backend/textbook_processing/deep_toc_parser.py` (518行) **Batch 4 — 基础设施层 (~2,980行)** - `backend/cache/manager.py` (858行) - `backend/cache/redis_cache.py` (615行) - `backend/gateway/router.py` (285行) - `backend/gateway/rate_limiter.py` (265行) - `backend/gateway/circuit_breaker.py` (254行) - `backend/domains/base.py` (216行) - `backend/domains/registry.py` (281行) - `backend/common/db_helpers.py` (206行) **Batch 5 — Auth系统 (~2,685行)** - `backend/auth/__init__.py` (129行) - `backend/auth/jwt.py` (810行) - `backend/auth/middleware.py` (628行) - `backend/auth/rbac.py` (1,118行) **Batch 6 — 部署与附加 (3,015+行)** - `docker-compose.yml` (226行) - `nginx/nginx.conf` (72行) - `backend/Dockerfile` (32行) - `backend/main.py` (83行) - `backend/core/lifespan.py` (228行) - `backend/core/middleware.py` (134行) - `backend/core/services.py` (337行) - `backend/core/service_manager.py` (334行) - `backend/core/database.py` (50行) - `backend/core/dependency_injection.py` (316行) - `backend/core/request_stats.py` (21行) - `backend/monitoring/__init__.py` (30行) - `backend/monitoring/health.py` (298行) - `backend/monitoring/metrics.py` (293行) - `backend/monitoring/prometheus.py` (133行) - `backend/cache/__init__.py` (77行) - `backend/cache/decorators.py` (698行) - `backend/gateway/__init__.py` (17行) - `backend/domains/__init__.py` (25行) - `backend/common/__init__.py` (32行) - `backend/utils/path_validation.py` (108行)2. CRITICAL — 必须立即修复
🔴 C-1: 向量搜索为桩代码(STUB)— 所有语义搜索返回垃圾结果
文件: backend/services/retrieval/vector.py:79-95
严重性: 🔴 CRITICAL
影响: 所有向量搜索、混合搜索、GraphRAG推理的结果均不可信
# vector.py:79-95 — embed_text() 的实际实现
# TODO: 集成实际的BGE嵌入服务
# 目前使用简单哈希模拟(生产环境需替换)
import hashlib
hash_obj = hashlib.sha256(text.encode('utf-8'))
hash_bytes = hash_obj.digest()
# 扩展到1024维
vector = []
for i in range(self.embedding_dim):
byte_idx = i % len(hash_bytes)
val = (hash_bytes[byte_idx] / 255.0 - 0.5) * 2
vector.append(val)
# 归一化
norm = sum(v * v for v in vector) ** 0.5
vector = [v / norm for v in vector]
问题:
- hashlib.sha256 生成的是确定性伪随机数,不是语义向量
- 相似的文本不会得到相似的向量,不同的文本也不会被区分
- 整个1024维向量仅由32字节(256位)的哈希循环填充,信息量极低
- search_by_vector() 同样是桩代码
- 注释明确说 "TODO: 集成实际的BGE嵌入服务" 和 "生产环境需替换"
影响范围:
- POST /api/v1/search/hybrid — 混合搜索(BM25 + 向量)
- POST /api/v1/reasoning/graphrag — GraphRAG推理
- backend/services/retrieval/hybrid.py — RRF融合排序
- 所有依赖向量相似度的功能
修复方案: 集成真实嵌入模型(BGE-M3 / text2vec-large-chinese / OpenAI embeddings)
🔴 C-2: 认证系统已构建但完全未启用
文件: backend/main.py:49-67(中间件注册), backend/auth/(~2,685行代码)
严重性: 🔴 CRITICAL
影响: 所有API端点完全开放,无认证
详细分析:
| 模块 | 文件 | 行数 | 状态 |
|---|---|---|---|
| JWT | auth/jwt.py |
810 | ✅ 完整实现(RS256、黑名单、刷新令牌) |
| 中间件 | auth/middleware.py |
628 | ✅ 完整实现 |
| RBAC | auth/rbac.py |
1,118 | ✅ 完整实现(权限、角色、条件) |
| 导出 | auth/__init__.py |
129 | ✅ 完整实现 |
未启用的证据 (main.py:49-67):
# main.py 中注册的5个中间件:
app.add_middleware(CORSMiddleware, ...) # CORS
app.middleware("http")(add_security_headers) # 安全头
app.middleware("http")(log_requests) # 请求日志
app.add_middleware(GZipMiddleware, ...) # GZip
app.add_middleware(RateLimitMiddleware) # 限流
# ❌ 没有 AuthMiddleware
完全开放的端点:
- POST /api/v1/documents — 创建文档(无认证)
- POST /api/v1/search/embeddings/update — 更新嵌入(无认证)
- POST /api/v1/gateway/query — 网关查询(无认证)
- POST /api/v1/domains/{name}/query — 领域查询(无认证)
- POST /api/v1/reasoning/* — 所有推理端点(无认证)
修复方案: 在 main.py 中添加 AuthMiddleware,为路由添加认证依赖
🔴 C-3: SQL注入 — db_helpers.py 中 f-string 拼接 SQL
文件: backend/common/db_helpers.py:98-103
严重性: 🔴 CRITICAL(升级自HIGH — 直接SQL注入向量)
影响: 如果 query 参数来源可被用户控制,攻击者可执行任意SQL
# db_helpers.py:98-103 — fetch_paginated() 函数
count_query = f"SELECT COUNT(*) FROM ({query}) AS subq" # ← 直接拼接
total = await pool.fetchval(count_query, *args)
# 获取分页数据
paginated_query = f"{query} ORDER BY id LIMIT ${len(args) + 1} OFFSET ${len(args) + 2}"
rows = await pool.fetch(paginated_query, *args, limit, offset) # ← 直接拼接
问题: query 参数通过 f-string 直接插入到 SQL 语句中。虽然当前调用者的 query 都是硬编码字符串,但函数签名接受任意字符串,一旦有调用者传入用户控制的查询,即为 SQL 注入。
修复方案:
1. 将 query 参数改为枚举或白名单验证
2. 或者将整个函数标记为内部API,禁止传入动态SQL
🔴 C-4: LingFlow workflow.py 中遗留的 sys.path hack(step4/step5未修复)
文件: backend/textbook_processing/workflow.py:508-509, 576-577
严重性: 🔴 CRITICAL(针对LingFlow启用)
影响: step4 和 step5 的导入会因路径错误而失败
# workflow.py:508-509 — step4_import_to_db() 中
import sys
sys.path.insert(0, str(self.project_root / "backend" / "lingflow")) # ← 路径已不存在
# workflow.py:576-577 — step5 中
import sys
sys.path.insert(0, str(self.project_root / "scripts")) # ← 路径可能不存在
背景: Phase 5 修复了 step3 的路径问题(line 423),但遗漏了 step4 (line 508) 和 step5 (line 577)。
修复方案: 更新为 backend/textbook_processing/ 路径
3. HIGH — 高优先级修复
🟠 H-1: Config 单例线程不安全 — get_config() 无锁保护
文件: backend/config/__init__.py:88-101
严重性: 🟠 HIGH
影响: 并发初始化时可能创建多个 Config 实例
# config/__init__.py:88-101
_config: Optional[Config] = None
_config_lock = asyncio.Lock() # ← 锁存在但...
def get_config() -> Config: # ← 同步函数,不使用 _config_lock
"""获取配置实例(单例模式)"""
global _config
if _config is None:
_config = Config() # ← 竞态条件
return _config
_config_lock 在 line 89 定义但 get_config() 是同步函数,无法使用 asyncio.Lock。只有 reload_config() 使用了该锁。
修复方案: 使用 threading.Lock 替代 asyncio.Lock,在 get_config() 中加锁。
🟠 H-2: ServiceManager 单例无锁保护
文件: backend/core/service_manager.py:315-328
严重性: 🟠 HIGH
# service_manager.py:315-328
_global_service_manager: Optional[ServiceManager] = None
def get_service_manager() -> ServiceManager:
global _global_service_manager
if _global_service_manager is None:
_global_service_manager = ServiceManager() # ← 无锁,竞态条件
return _global_service_manager
与 H-1 相同模式。ServiceManager 自身有 self._lock = asyncio.Lock() (line 110),但工厂函数无保护。
修复方案: 使用 threading.Lock 保护单例创建。
🟠 H-3: Redis URL 双源冲突 — REDIS_URL vs get_redis_url()
文件: backend/config/redis.py:21-24 + backend/config/redis.py:87-91
严重性: 🟠 HIGH
影响: Docker 环境下实际使用的 Redis URL 可能与配置不一致
# redis.py:21-24 — 字段默认值
REDIS_URL: str = Field(
default="redis://localhost:6379/0",
description="Redis连接URL"
)
# redis.py:87-91 — 方法构建URL
def get_redis_url(self) -> str:
if self.REDIS_PASSWORD:
return f"redis://:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
return f"redis://{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
冲突:
- Docker Compose 设置 REDIS_URL=redis://redis:6379/0(容器名解析)
- REDIS_HOST 默认 localhost(不在 Docker 中)
- get_redis_url() 从组件构建,忽略 REDIS_URL 字段
- Phase 6 修复了 services.py:133 使用 config.get_redis_url(),但这依赖组件配置正确
修复方案: get_redis_url() 应优先返回 REDIS_URL(如果已设置),仅在没有完整URL时从组件构建。
🟠 H-4: 健康检查泄露数据库错误详情
文件: backend/core/lifespan.py:154-159 + backend/common/db_helpers.py:201-205
严重性: 🟠 HIGH
影响: 内部错误详情(可能含连接串)暴露给API调用者
# lifespan.py:154-159
except Exception as e:
return HealthCheckResult(
name="database",
status=HealthStatus.UNHEALTHY,
message=f"数据库连接失败: {str(e)}" # ← 泄露完整错误
)
# db_helpers.py:201-205
return {
"status": "degraded",
"database": f"error: {str(e)}", # ← 泄露完整错误
"timestamp": datetime.now().isoformat(),
}
asyncpg 的异常消息通常包含完整的连接字符串(主机、端口、数据库名、用户名)。
修复方案: 使用通用错误消息,将详细信息仅记录到日志。
🟠 H-5: 数据库连接池大小硬编码,忽略配置
文件: backend/core/database.py:28-34
严重性: 🟠 HIGH
# database.py:28-34
db_pool = await asyncpg.create_pool(
database_url,
min_size=10, # ← 硬编码
max_size=50, # ← 硬编码
command_timeout=30,
max_inactive_connection_lifetime=300
)
Config 类有 DB_POOL_SIZE 字段,但 init_db_pool() 从不读取它。直接使用 os.getenv("DATABASE_URL") (line 22) 而非配置系统。
修复方案: 从 get_config() 读取池大小配置。
🟠 H-6: Triple 数据库连接池问题
文件: 多个文件 严重性: 🟠 HIGH 影响: 连接泄漏、资源浪费
| 池来源 | 文件 | 创建方式 |
|---|---|---|
| 池 #1 | core/lifespan.py |
通过 DatabaseService.start() |
| 池 #2 | core/services.py |
VectorService.start() 再次调用 init_db_pool() |
| 池 #3 | core/dependency_injection.py |
弃用的 _db_pool 仍存在 |
修复方案: 统一为单一池,通过 app.state.db_pool 共享。
🟠 H-7: 写入端点无认证
严重性: 🟠 HIGH(依赖 C-2 修复)
以下端点接受写入操作但完全无认证:
| 端点 | 方法 | 风险 |
|---|---|---|
/api/v1/documents |
POST | 创建任意文档 |
/api/v1/search/embeddings/update |
POST | 修改嵌入数据 |
/api/v1/reasoning/* |
POST | 推理调用(消耗API配额) |
4. MEDIUM — 中等优先级
🟡 M-1: Redis 健康检查使用过时的 aioredis API
文件: backend/monitoring/health.py:262-263
严重性: 🟡 MEDIUM
aioredis 已合并到 redis>=4.2.0。应使用 import redis.asyncio as aioredis。
🟡 M-2: 模块级可变全局状态(非线程安全)
文件: backend/api/v1/search.py:23-33, backend/api/v1/reasoning.py:22-24
# search.py:23
_hybrid_retriever: Optional[HybridRetriever] = None # ← 模块级可变全局
# reasoning.py:22-24
_cot_reasoner: Optional[ChainOfThoughtReasoner] = None
_react_reasoner: Optional[ReActReasoner] = None
_graphrag_reasoner: Optional[GraphRAGReasoner] = None
多个协程可能同时读写这些全局变量。
🟡 M-3: 网关限流硬编码 client_ip — 所有用户共享限流桶
文件: backend/api/v1/gateway.py:85
严重性: 🟡 MEDIUM
所有用户共享同一个 "default" 限流桶,一个用户的请求会影响所有用户。
修复方案: 从 Request.client 或 X-Forwarded-For 头提取真实IP。
🟡 M-4: 任务ID生成基于秒级时间戳 — 并发冲突
文件: backend/api/v1/textbook_processing.py:152, 218
严重性: 🟡 MEDIUM
# textbook_processing.py:152
task_id = f"task_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
# textbook_processing.py:218
task_id = f"batch_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
同一秒内的并发请求会产生相同的 task_id,后者覆盖前者。
修复方案: 使用 uuid.uuid4() 或加入毫秒/随机后缀。
🟡 M-5: RBACManager.init 中调用 asyncio.create_task
文件: backend/auth/rbac.py:522
严重性: 🟡 MEDIUM
如果实例化时没有运行中的事件循环(如模块导入、测试环境),会抛出 RuntimeError。
修复方案: 改为显式的异步初始化方法(async def initialize())。
🟡 M-6: 缓存端点泄露异常信息
文件: backend/api/v1/health.py:119, 137, 161, 192, 211
严重性: 🟡 MEDIUM
# health.py:119 — cache stats
return {"error": str(e), "enabled": False}
# health.py:137 — cache metrics
return {"error": str(e), "enabled": False}
# health.py:161 — prometheus endpoint
content=f"# Error: {str(e)}"
# health.py:192, 211 — reset/clear endpoints
return {"status": "error", "message": str(e)}
5处异常直接暴露给API调用者,可能泄露内部路径、配置或堆栈信息。
修复方案: 使用通用错误消息 + 日志记录。
🟡 M-7: Nginx 缺少 client_max_body_size 配置
文件: nginx/nginx.conf(全文72行,无此指令)
严重性: 🟡 MEDIUM
影响: 教材文件上传(通常数MB至数十MB)会被 nginx 默认的 1MB 限制拒绝(413错误)
修复方案: 在 server 块中添加 client_max_body_size 100M;
🟡 M-8: Dockerfile CMD 使用开发模式 --reload
文件: backend/Dockerfile:32
严重性: 🟡 MEDIUM
虽然 docker-compose.yml 覆盖了此命令,但直接 docker build && docker run 时会使用开发模式。
修复方案: 移除 --reload。
🟡 M-9: LingZhiConfig 与 DatabaseConfig 字段重复
文件: backend/config/lingzhi.py vs backend/config/database.py
严重性: 🟡 MEDIUM
| 字段 | LingZhiConfig 行号 |
DatabaseConfig 行号 |
|---|---|---|
GUOXUE_DB_PATH |
line 22 | line 28 |
KXZD_DB_PATH |
line 26 | line 32 |
QUERY_TIMEOUT |
line 49 | line 69 |
MAX_CONNECTIONS vs DB_MAX_CONNECTIONS |
line 56 | line 61 |
MRO 导致 LingZhiConfig 值可能覆盖 DatabaseConfig 值。
🟡 M-10: LIKE 通配符注入
文件: backend/common/db_helpers.py:135
严重性: 🟡 MEDIUM
search_term 中的 % 和 _ 不会被转义,用户可以通过输入 % 匹配所有行。虽然不是SQL注入(参数化安全),但影响查询准确性。
修复方案: search_term.replace('%', '\\%').replace('_', '\\_') 预处理。
🟡 M-11: Docker Compose postgres-exporter 端口错误
文件: docker-compose.yml:198
严重性: 🟡 MEDIUM
# docker-compose.yml:198
DATA_SOURCE_NAME: "postgresql://zhineng:${POSTGRES_PASSWORD:-zhineng123}@postgres:5436/zhineng_kb?sslmode=disable"
postgres:5436 错误。Docker 内部网络中 PostgreSQL 监听 5432(5436:5432 是宿主映射)。exporter 运行在同一 Docker 网络中,应使用内部端口 5432。
🟡 M-12: Config 模块级加载
文件: backend/config/__init__.py:137(近似)
严重性: 🟡 MEDIUM
任何 from config import ... 都会立即创建 Config 实例,影响测试隔离。
🟡 M-13: 两套独立的限流系统
文件: backend/api/v1/gateway.py + backend/core/middleware.py
严重性: 🟡 MEDIUM
- 中间件层:
RateLimitMiddleware— 全局请求限流 - 网关层:
InMemoryRateLimiter— 端点级别限流
两者独立运行,互不感知,可能导致限流不一致。
🟡 M-14: Docker Compose 默认密码弱
文件: docker-compose.yml
ADMIN_API_KEYS 默认为 admin123。
5. LOW — 代码质量与清理
🟢 L-1: 大量备份文件污染仓库
main.py.backup
main.py.backup_before_refactor
db_helpers.py.backup
docker-compose.yml.backup.*
docker-compose.yml.bad
修复: 删除所有 .backup 文件,依赖 Git 历史
🟢 L-2: 监控模块零测试覆盖
backend/monitoring/ 模块完全没有测试。健康检查、指标收集、Prometheus 导出器未经测试。
🟢 L-3: 未使用的核心模块
| 模块 | 行数 | 说明 |
|---|---|---|
common/singleton.py |
~30 | 导出但从未被实际服务代码导入 |
core/config_watcher.py |
197 | 零覆盖,集成路径不明 |
core/urgency_guard.py |
184 | 零覆盖,集成路径不明 |
core/data_verification_gate.py |
~190 | 零覆盖,集成路径不明 |
🟢 L-4: Elasticsearch 已部署但未使用
docker-compose.yml 包含 tcm-elasticsearch 服务(运行中),但代码中没有 Elasticsearch 集成。BM25 使用内存索引,浪费了已部署的 ES 实例。
🟢 L-5: TextbookImporter 使用 print() 而非 logging
文件: backend/services/textbook_importer.py
🟢 L-6: Nginx 无 HTTPS 配置
文件: nginx/nginx.conf — 仅监听 80 端口
🟢 L-7: main.py 使用 sys.path.insert
允许无 backend. 前缀的导入,但在不同工作目录运行时会崩溃。
6. LingFlow 启用分析
6.1 当前状态
LingFlow 是灵知系统的教材处理流水线,包含以下组件:
| 组件 | 文件 | 行数 | 状态 |
|---|---|---|---|
| 自动处理器 | textbook_processing/autonomous_processor.py |
962 | ✅ 输出路径已修复 |
| 工作流引擎 | textbook_processing/workflow.py |
808 | ⚠️ step4/step5路径未修复 |
| 深度目录解析 | textbook_processing/deep_toc_parser.py |
518 | ✅ 可用 |
| 教材服务 | services/textbook_service.py |
306 | ✅ 可用 |
| API端点 | api/v1/textbook_processing.py |
295 | ✅ 受API Key保护 |
| 上下文压缩 | services/compression.py |
528 | ✅ 可用 |
6.2 LingFlow 数据流
PDF教材 → autonomous_processor.py → TOC提取(deep_toc_parser) → 文本分段 → 结构化数据
↓
textbook_service.py → 入库到 PostgreSQL
↓
vector.py(桩代码) → 生成"嵌入"(SHA-256哈希)
↓
bm25.py(jieba分词) → 关键词索引 ✅ 已修复
↓
hybrid.py → RRF混合搜索(向量部分不可信)
结论: LingFlow 的处理流水线(PDF → 结构化数据)基本可用,但 step4/step5 路径未修复、检索环节的向量部分完全不工作。
6.3 启用 LingFlow 的阻塞项
- ~~路径更新~~ — ✅ step3 已修复,❌ step4 (workflow.py:508) 和 step5 (workflow.py:577) 未修复
- ~~中文分词~~ — ✅ 已集成 jieba + 自定义词典
- 嵌入服务 — ❌ 向量搜索仍为桩代码
- 认证激活 — textbook-processing 端点有 API Key 保护,可独立使用
7. 审计发现汇总表
| # | 严重性 | 问题 | 文件:行号 | 修复工作量 |
|---|---|---|---|---|
| C-1 | 🔴 CRITICAL | 向量搜索为桩代码 | services/retrieval/vector.py:79-95 |
大(需集成嵌入模型) |
| C-2 | 🔴 CRITICAL | 认证系统未启用 | main.py:49-67, auth/ |
中(代码已写好,需接线) |
| C-3 | 🔴 CRITICAL | SQL注入(f-string) | common/db_helpers.py:98-103 |
中(重构分页函数) |
| C-4 | 🔴 CRITICAL | LingFlow step4/5路径未修复 | workflow.py:508-509, 576-577 |
小(改路径) |
| H-1 | 🟠 HIGH | Config单例无锁 | config/__init__.py:88-101 |
小(加threading.Lock) |
| H-2 | 🟠 HIGH | ServiceManager单例无锁 | service_manager.py:315-328 |
小(加threading.Lock) |
| H-3 | 🟠 HIGH | Redis URL双源冲突 | config/redis.py:21-24, 87-91 |
中(统一URL来源) |
| H-4 | 🟠 HIGH | 健康检查泄露错误 | lifespan.py:154-159, db_helpers.py:201-205 |
小 |
| H-5 | 🟠 HIGH | DB池大小硬编码 | database.py:28-34 |
小 |
| H-6 | 🟠 HIGH | Triple连接池 | 多个文件 | 中(重构) |
| H-7 | 🟠 HIGH | 写入端点无认证 | 多个API文件 | 依赖C-2 |
| M-1 | 🟡 MEDIUM | aioredis过时API | monitoring/health.py:262-263 |
小 |
| M-2 | 🟡 MEDIUM | 模块级可变全局 | search.py:23, reasoning.py:22-24 |
小 |
| M-3 | 🟡 MEDIUM | 限流client_ip硬编码 | gateway.py:85 |
小 |
| M-4 | 🟡 MEDIUM | 任务ID时间戳冲突 | textbook_processing.py:152, 218 |
小 |
| M-5 | 🟡 MEDIUM | RBAC init中create_task | rbac.py:522 |
中 |
| M-6 | 🟡 MEDIUM | 缓存端点泄露异常 | health.py:119,137,161,192,211 |
小 |
| M-7 | 🟡 MEDIUM | nginx无body大小限制 | nginx/nginx.conf |
小 |
| M-8 | 🟡 MEDIUM | Dockerfile --reload | Dockerfile:32 |
小 |
| M-9 | 🟡 MEDIUM | 配置字段重复 | lingzhi.py vs database.py |
中 |
| M-10 | 🟡 MEDIUM | LIKE通配符注入 | db_helpers.py:135 |
小 |
| M-11 | 🟡 MEDIUM | postgres-exporter端口错 | docker-compose.yml:198 |
小 |
| M-12 | 🟡 MEDIUM | Config模块级加载 | config/__init__.py:~137 |
中 |
| M-13 | 🟡 MEDIUM | 双重限流系统 | gateway.py + middleware.py |
中 |
| M-14 | 🟡 MEDIUM | 默认密码弱 | docker-compose.yml |
小 |
| L-1 | 🟢 LOW | 备份文件 | 多个 | 小 |
| L-2 | 🟢 LOW | 监控无测试 | monitoring/ |
大 |
| L-3 | 🟢 LOW | 未使用模块 | 多个 | 中 |
| L-4 | 🟢 LOW | ES未使用 | docker-compose | 中 |
| L-5 | 🟢 LOW | print代替logging | textbook_importer.py |
小 |
| L-6 | 🟢 LOW | 无HTTPS | nginx/nginx.conf |
中 |
| L-7 | 🟢 LOW | sys.path hack | main.py |
小 |
统计: 4 CRITICAL / 7 HIGH / 14 MEDIUM / 7 LOW = 32 项发现
8. 修复优先级路线图(Phase 7-12)
Phase 7: 安全加固(3-4小时)⭐ 优先
目标: 消除直接的SQL注入和错误泄露
- [ ] C-3: 重构
db_helpers.py:fetch_paginated()— 使用白名单验证 query 参数 - [ ] H-4: 修复
lifespan.py:158和db_helpers.py:203— 通用错误消息 + 日志记录 - [ ] M-6: 修复
health.py5处str(e)泄露 — 通用错误消息 - [ ] M-10: 修复
db_helpers.py:135— LIKE通配符转义 - [ ] M-11: 修复
docker-compose.yml:198— postgres-exporter 端口改为 5432
Phase 8: 认证系统激活(3-4小时)
目标: 保护所有API端点
- [ ] C-2: 在
main.py中添加AuthMiddleware - [ ] 为写入端点添加
get_authenticated_user依赖 - [ ] 为读取端点添加可选认证(API Key 或 JWT)
- [ ] M-5: 修复
rbac.py:522— 改为显式异步初始化 - [ ] 补全
requirements.txt中缺失的cryptography,pyjwt
Phase 9: 配置与单例安全(2-3小时)
目标: 消除竞态条件和配置冲突
- [ ] H-1:
config/__init__.py:92—get_config()改用threading.Lock - [ ] H-2:
service_manager.py:318—get_service_manager()改用threading.Lock - [ ] H-3:
config/redis.py:87—get_redis_url()优先使用REDIS_URL - [ ] H-5:
database.py:28— 从配置读取池大小 - [ ] M-9: 清理
LingZhiConfig与DatabaseConfig的重复字段 - [ ] M-12: Config 改为懒加载
Phase 10: LingFlow 完整启用(2-3小时)
目标: 让 LingFlow 全流水线可运行
- [ ] C-4: 修复
workflow.py:508-509— step4 的 sys.path.insert - [ ] C-4: 修复
workflow.py:576-577— step5 的 sys.path.insert - [ ] 端到端测试 LingFlow 流水线(PDF → 入库)
- [ ] M-4:
textbook_processing.py:152,218— 任务ID改用 uuid4
Phase 11: 连接池统一 + 清理(2-3小时)
目标: 消除冗余连接
- [ ] H-6: 移除 API 文件中的直接
init_db_pool()调用 - [ ] 统一使用
app.state.db_pool - [ ] 移除 DI 中弃用的
_db_pool - [ ] M-7: nginx 添加
client_max_body_size 100M - [ ] M-8: Dockerfile 移除
--reload - [ ] L-1: 清理备份文件
Phase 12: 向量嵌入集成(4-8小时)
目标: 替换桩代码,实现真正的语义搜索
- [ ] C-1: 选择并集成嵌入模型
- [ ] 实现真实的
embed_text()和embed_texts() - [ ] 实现真实的
search_by_vector() - [ ] 对已有文档重新生成嵌入
- [ ] 更新混合搜索权重
决策点
以下决策需要您的输入:
1. 嵌入模型选择
- BGE-M3 (BAAI): 多语言,支持中文,需要本地 GPU 或远程 API
- text2vec-large-chinese: 中文优化,可本地部署
- OpenAI embeddings: 需要 API 密钥,简单集成但依赖外部服务
- DeepSeek API: 系统已配置 DeepSeek,可以复用
2. 认证策略
- 全面激活 JWT+RBAC: 使用已构建的完整认证系统
- 仅 API Key: 更简单,适合内部系统
- 渐进式: 先 API Key,后 JWT
3. Elasticsearch 利用
- 系统已部署 ES(
tcm-elasticsearch),是否用于 BM25 替代内存索引?
审计结论: 灵知系统的架构设计合理,代码量充足(~14,000行),基础设施完善。Phase 1-6 已修复路径遍历、API密钥保护、LingFlow step3路径、jieba分词集成、Redis缓存修复等问题。当前 4 个 CRITICAL 阻塞问题:向量搜索为桩代码(C-1)、认证未启用(C-2)、SQL注入(C-3)、LingFlow step4/5路径未修复(C-4)。建议按 Phase 7-12 路线图逐步修复,优先处理 Phase 7(安全加固)和 Phase 8(认证激活),因为这两项投入产出比最高——代码已写好,只需接线。
附录 A: 关联文档索引
| 文档 | 内容 | 与本报告关系 |
|---|---|---|
COMPREHENSIVE_SECURITY_AUDIT_REPORT.md |
安全专项审计(基于 main_optimized.py) |
互补。该报告分析了简化版主文件,部分发现已在本报告中覆盖 |
SECURITY_RESOURCE_EMERGENCY_RESPONSE_PLAN.md |
安全×资源紧急响应计划(72小时加固方案) | 互补。覆盖容器资源限制、监控告警、应急恢复 |
ROOT_CAUSE_ANALYSIS_20260330.md |
高资源占用根因分析(内存96%危机) | 前置。资源问题已通过磁盘清理和容器限制缓解 |
OPTIMIZATION_ROADMAP_20260330.md |
基础设施优化路线图 | 互补。聚焦基础设施层,本报告聚焦应用代码层 |
LINGFLOW_VALUE_CREATION_ANALYSIS_20260330.md |
LingFlow战略转型分析(AI编码工具增强引擎) | 战略层。定义了LingFlow的产品方向和技术路线 |
ANALYSIS_SUMMARY.md |
分析汇总 | 综合摘要 |
附录 B: main_optimized.py 审计补充
系统存在一个独立的简化版入口文件 backend/main_optimized.py(~220行),与主入口 main.py(~83行)并行存在。该文件在 COMPREHENSIVE_SECURITY_AUDIT_REPORT.md 中被重点分析。以下是该文件的额外发现:
B-1: 并行入口文件造成混淆
main.py是当前 docker-compose.yml 启动的入口(通过CMD覆盖)main_optimized.py是一个独立的简化版入口,自带路由和数据库逻辑- 两者注册不同的中间件和路由,如果错误启动
main_optimized.py,安全配置不一致
B-2: main_optimized.py 的安全改进(相对于 main.py)
| 改进项 | main.py |
main_optimized.py |
|---|---|---|
| CORS 配置 | 已修复为白名单(Phase 1) | 已使用白名单 + ALLOWED_ORIGINS 环境变量 |
| 硬编码密码 | 使用 env var(无默认值) | 正确抛出 ValueError(无默认值) |
| 裸异常 | 存在 | 已修复为具体异常类型 |
B-3: main_optimized.py 的遗留问题
stats端点使用asyncio.gather()但文件底部if __name__才import asyncio(运行时错误)- LIKE 通配符未转义(与
db_helpers.py:135相同问题) - 无认证保护(与
main.py相同) - 单文件连接池(
get_db()中的全局pool)与主系统连接池无关
B-4: 建议
main_optimized.py 中的安全改进(CORS白名单、强制环境变量)应回移到主系统的 SecurityConfig 中。该文件本身可考虑删除或归档,避免混淆。