skillhub/scanner/docs/failure-impact-analysis.md
XiaoSeS 3bc97ff1b8 feat(security): add security scanning system with multi-scanner support and frontend UI (#144)
* feat(security): extend scanner config with full analyzer options

Integrate skill-scanner's 8 analysis engines and policy configuration
into SkillHub's config system. Operators can now control behavioral,
LLM, Meta, AI Defense, VirusTotal, and trigger analyzers via
application.yml or environment variables.

Changes:
- Add Analyzers and Policy nested classes to SkillScannerProperties
- Create ScanOptions record to encapsulate analyzer flags
- Update SkillScannerService to pass options in /scan body and /scan-upload query params
- Wire ScanOptions through SkillScannerConfig and SkillScannerAdapter
- Extend application.yml with full scanner config block and env var overrides
- Update all tests to verify new configuration flow

All tests pass.

* feat(security): add domain model and integrate scan into publish flow

Add SCANNING/SCAN_FAILED status to SkillVersionStatus. Introduce
SecurityScanService, SecurityScanner port, ScanTask, SecurityAudit
and related domain types. Wire scan trigger into SkillPublishService
so non-auto-publish versions enter scanning when scanner is enabled,
falling back to review task creation when disabled.

* feat(security): add infra layer for scanner HTTP client and adapters

Add WebClient-based HttpClient abstraction with WebClientHttpClient
implementation. Add SkillScannerApiResponse record, SecurityScanException,
and SecurityAuditJpaRepository. Add webflux and test dependencies to
infra module.

* feat(security): add Redis stream consumers, audit API, and DB migration

Add AbstractStreamConsumer base class, ScanTaskConsumer for processing
scan results from Redis stream, and RedisScanTaskProducer. Add
RedisStreamConfig for stream/group initialization. Add SecurityAudit
REST controller and DTO. Add V35 Flyway migration for security_audits
table.

* feat(security): add scanner config to application profiles

Add scanner enabled flag to application-local.yml and
application-test.yml. Enable behavioral analyzer by default
in application.yml.

* feat(deploy): add skill-scanner to docker-compose and k8s manifests

Add skill-scanner service to docker-compose.yml with health check.
Add scanner k8s deployment, service, and configmap entries. Wire
scanner env vars into Makefile dev-all flow. Add verify-scanner.sh
script for post-deploy validation.

* docs(security): add scanner documentation suite

Add scanner docs: configuration guide, failure impact analysis,
monitoring guide, improvement recommendations, custom rules guide,
and skill-vetter rules conversion example. Update deployment docs
with scanner section. Add security-scanning overview and PRD.

* feat(security): add skill-vetter custom rule examples

Add example Regex and YARA rules derived from skill-vetter RED FLAGS
in scanner/examples/vetter-rules/. Includes 7 Regex rules
(signatures-append.yaml) and 3 YARA rules (skillhub_vetter.yara)
covering agent memory theft, IP-based exfiltration, and browser
data theft detection.

* feat(security): add scanner Docker build context

Add Dockerfile for cisco-ai-skill-scanner container and
.env.example with LLM configuration placeholders.

* fix(security): align Finding mapping with scanner API response schema

SkillScannerApiResponse.Finding used incorrect field names (message,
location.file, location.line, code_snippet) that did not match the
scanner's actual JSON output (description, file_path, line_number,
snippet), causing all four fields to deserialize as null.

Flatten Finding to match scanner API: remove nested Location, rename
fields to description/file_path/line_number/snippet. Add skill_name
and timestamp to SkillScannerApiResponse. Extend SecurityFinding with
remediation, analyzer, and metadata fields to capture LLM analyzer
output. Retain 8-arg compact constructor for backward compatibility.

* chore(security): add debug logging to scanner response mapping

Log raw scanner API response and mapped SecurityFinding fields
side-by-side to help verify data consistency between scanner
output and database records.

* feat(security): add multi-scanner support and soft delete for security audits

- Add ScannerType enum for type-safe scanner identification
- Update V35 migration to support multiple scanners and soft delete
- Remove CASCADE delete, use code-level soft delete (deleted_at)
- Add repository methods for querying latest audit by scanner type
- Update SecurityScanService to handle scanner type parameter
- Integrate soft delete in SkillHardDeleteService
- Update all tests to use ScannerType enum

This enables multiple scanner integrations (skill-scanner, future LLM/compliance scanners)
and preserves complete audit history through soft deletion.

* feat(security): add security audit UI to review detail and skill detail pages

Display security scan results on the review detail page (full audit
section with collapsible findings) and the skill detail sidebar (compact
summary with dialog for details).  Handles empty/404 gracefully by
returning null, avoids loading shimmer flicker, and separates lifecycle
action buttons with a visual divider.

* docs(security): add security audit UI PRD

* fix(security): replace LocalDateTime with Instant in security audit and align controller test with list API

SecurityAudit and SecurityScanService used LocalDateTime.now() which
violated the project time guardrail. Replaced with Instant and
Clock.systemUTC() to match existing conventions.

Also fixed SecurityAuditControllerTest to mock the correct repository
method (findLatestActiveByVersionId) and assert against the list
response shape.

* test(security): add useQuery mock for security audit components in frontend tests

The SecurityAuditSummary and SecurityAuditSection components use
useQuery via useSecurityAudits hook, which was missing from the
@tanstack/react-query mocks in skill-detail and review-detail tests.
2026-03-23 09:56:03 +08:00

5.2 KiB
Raw Blame History

Scanner 接口故障影响分析

概述

本文档分析 Cisco skill-scanner API 接口出现故障时对 SkillHub 系统的影响,以及当前的错误处理机制。

故障场景分类

场景 AScanner 服务完全不可用

现象

  • HTTP 连接超时
  • 服务宕机
  • 网络不通

影响

  • 技能包发布流程中断
  • 技能版本状态卡在 SCANNING
  • ⚠️ 用户无法继续发布新版本

场景 BScanner 服务响应慢

现象

  • 扫描超时(默认 5 分钟 read timeout

影响

  • ⚠️ 发布流程变慢
  • ⚠️ Redis Stream 消息堆积
  • ⚠️ 可能触发重试机制

场景 CScanner 返回错误响应

现象

  • HTTP 4xx/5xx 错误

影响

  • 扫描任务失败
  • 自动降级到人工审核流程

错误处理机制(当前实现)

处理流程

发布技能包
    ↓
triggerScan() → 创建 SecurityAudit + 发送 Redis 消息
    ↓
版本状态 → SCANNING
    ↓
ScanTaskConsumer 消费消息
    ↓
调用 securityScanner.scan()
    ↓
┌─────────────────────────────────────┐
│ 如果 Scanner 接口失败:              │
│                                     │
│ 1. 抛出 SecurityScanException       │
│ 2. AbstractStreamConsumer 捕获异常  │
│ 3. 调用 markFailed()                │
│ 4. 版本状态 → SCAN_FAILED           │
│ 5. 自动创建 ReviewTask              │
│ 6. 清理临时文件                      │
│ 7. 重试机制(最多 3 次)             │
└─────────────────────────────────────┘

关键代码位置

错误处理逻辑

  • ScanTaskConsumer.markFailed() - server/skillhub-app/src/main/java/com/iflytek/skillhub/stream/ScanTaskConsumer.java:104-119
@Override
protected void markFailed(ScanTaskPayload payload, String error) {
    try {
        skillVersionRepository.findById(payload.versionId)
                .filter(version -> version.getStatus() == SkillVersionStatus.SCANNING)
                .ifPresent(version -> {
                    version.setStatus(SkillVersionStatus.SCAN_FAILED);  // ← 标记失败
                    skillVersionRepository.save(version);
                    skillRepository.findById(version.getSkillId())
                            .ifPresent(skill -> reviewTaskRepository.save(
                                    new ReviewTask(payload.versionId, skill.getNamespaceId(), version.getCreatedBy())  // ← 降级到人工审核
                            ));
                });
    } finally {
        cleanupTempPath(payload.skillPath);  // ← 清理临时文件
    }
}

具体影响总结

故障类型 用户体验 系统行为 数据一致性 恢复方式
Scanner 宕机 发布失败,显示扫描失败 自动降级到人工审核 版本状态正确更新 自动恢复
网络超时 ⚠️ 等待 5 分钟后失败 重试 3 次后降级 状态一致 自动重试
Scanner 返回 5xx 扫描失败 降级到人工审核 状态一致 自动恢复
Scanner 返回 4xx 扫描失败 降级到人工审核 状态一致 需修复请求
Redis Stream 故障 消息丢失 版本卡在 SCANNING ⚠️ 需手动修复 需运维介入

潜在问题和风险

🔴 高风险问题

1. 版本状态卡死

场景:如果 Redis Stream 消费者未启动,或消息丢失

影响:版本永远停留在 SCANNING 状态

后果:用户无法继续发布,需要运维手动修复数据库

排查方法

-- 查找卡在 SCANNING 状态超过 10 分钟的版本
SELECT id, skill_id, version, status, created_at
FROM skill_versions
WHERE status = 'SCANNING'
  AND created_at < NOW() - INTERVAL 10 MINUTE;

2. 临时文件泄漏

场景:如果 markFailed()markCompleted() 未执行

影响/tmp/skillhub-scans/ 目录持续增长

后果:磁盘空间耗尽

排查方法

# 检查临时文件目录大小
du -sh /tmp/skillhub-scans/

# 查找超过 1 小时的临时文件
find /tmp/skillhub-scans/ -type f -mmin +60

🟡 中风险问题

3. 重试风暴

场景Scanner 持续返回 5xx 错误

影响:大量重试请求打满 Scanner 服务

后果Scanner 雪崩,影响其他技能包扫描

4. 审核队列堆积

场景Scanner 长期不可用,所有扫描失败

影响:所有技能包都降级到人工审核

后果:审核员工作量激增

当前实现的优缺点

优点

  • 有基本的错误处理和降级机制
  • 失败后自动创建人工审核任务
  • 有重试机制(最多 3 次)
  • 会清理临时文件

不足

  • 缺少熔断器,可能导致雪崩
  • 缺少超时监控,版本可能卡死
  • 缺少健康检查端点
  • 缺少详细的错误日志和指标

相关文档