# 【安全测试】执行计划 - 修复安全测试执行报错

> **文档类型**: 计划执行文档（安全测试模块）
> **创建日期**: 2026-07-21
> **关联问题**: `_问题处理_安全测试执行报错str对象无get属性.md`
> **执行策略**: 直接修复，无需分阶段

---

## 一、执行目标

修复安全测试模块执行时的 3 个问题，使安全测试用例能正常执行并保存结果。

| 修复点 | 优先级 | 目标 |
|--------|--------|------|
| 1. ORM 对象在 run_in_executor 中脱钩 | P0 | 安全测试用例正常执行 |
| 2. metadata 字段名冲突 | P0 | 漏洞结果正常保存 |
| 3. 前端 metadata 引用同步 | P0 | 接口返回正常 |

---

## 二、任务清单

### 2.1 后端修复

| # | 任务 | 文件 | 说明 |
|---|------|------|------|
| 1.1 | 重构 run_execution 执行逻辑 | `backend/app/services/security_service.py` | 在 async 上下文内预先转纯字典 |
| 1.2 | 修复字段名 metadata → extra_data | `backend/app/services/security_service.py` | `_save_vulnerability_result` |
| 1.3 | 修复 schema 字段名 | `backend/app/schemas/security.py` | `VulnerabilityResultResponse` |

### 2.2 前端修复

| # | 任务 | 文件 | 说明 |
|---|------|------|------|
| 2.1 | 同步类型定义 | `frontend/src/types/security.ts` | `VulnerabilityResult` 字段 |

### 2.3 验证

| # | 任务 | 说明 |
|---|------|------|
| 3.1 | 重启后端服务 | 加载新代码 |
| 3.2 | 执行安全测试 | 全部用例不再 error |
| 3.3 | 查看执行结果 | 漏洞结果正常保存 |

---

## 三、详细改动

### 3.1 后端：security_service.py（已实施）

#### 改动 A：run_execution 中预先转纯字典

**位置**: `run_execution()` 方法

**改动前**：
```python
def sync_run():
    executor.start()
    return executor.execute_cases(
        [{"id": c.id, "name": c.name, "steps": c.steps} for c in cases],
        ...
    )
results = await loop.run_in_executor(None, sync_run)
```

**改动后**：
```python
import json as _json

def _to_plain_steps(steps_val):
    """把 steps 字段统一转成 dict（兼容 str/dict/None）"""
    if isinstance(steps_val, str):
        try:
            parsed = _json.loads(steps_val)
            return parsed if isinstance(parsed, dict) else {}
        except Exception:
            return {}
    if isinstance(steps_val, dict):
        return steps_val
    return {}

# 在 async 上下文内（run_in_executor 之前）就完成转换
plain_cases = [
    {"id": c.id, "name": c.name, "steps": _to_plain_steps(c.steps)}
    for c in cases
]
client_config = config.to_client_config()

def sync_run():
    executor = SecurityExecutor(client_config)
    executor.start()
    return executor.execute_cases(plain_cases, ...)

results = await loop.run_in_executor(None, sync_run)
```

**原理**：线程池闭包只捕获纯字典数据，不再持有 ORM 对象引用，避免脱钩。

#### 改动 B：_save_vulnerability_result 字段名

**改动前**：
```python
vuln_result = VulnerabilityResult(
    ...
    metadata=result.metadata,
)
```

**改动后**：
```python
vuln_result = VulnerabilityResult(
    ...
    extra_data=result.metadata,
)
```

### 3.2 后端：schemas/security.py（已实施）

**改动**：`VulnerabilityResultResponse` 中 `metadata: Dict[str, Any]` → `extra_data: Dict[str, Any]`

### 3.3 前端：types/security.ts（待实施）

**改动**：`VulnerabilityResult` 接口中 `metadata: Record<string, any>` → `extraData: Record<string, any>`

---

## 四、验证检查清单

### 4.1 后端验证

- [ ] `security_service.py` 中 `run_execution` 已用 `_to_plain_steps` 预转换
- [ ] `security_service.py` 中 `_save_vulnerability_result` 已用 `extra_data`
- [ ] `schemas/security.py` 中 `VulnerabilityResultResponse` 已用 `extra_data`

### 4.2 执行验证

- [ ] 重启 8001 后端服务
- [ ] 前端 `/execution/security` 执行用例
- [ ] 全部用例状态为 passed/failed（不再 error）
- [ ] 执行记录可展开查看漏洞结果

### 4.3 时间显示（记录备案，不修复）

- [ ] 全项目时间显示问题单独评估（UTC → 本地时区转换）

---

## 五、风险评估

| 风险 | 影响 | 缓解 |
|------|------|------|
| 预转换逻辑遗漏嵌套字段 | 用例执行失败 | `_to_plain_steps` 兼容 str/dict/None 三种情况 |
| 前端未同步 extraData | 详情显示异常 | 前端 types 同步修改 |
| 现有执行记录数据 | 无 | 仅影响新执行，旧数据不受影响 |

---

*本文档为安全测试执行报错修复的计划执行文档。*
