| 维度 | 评级 | 说明 |
|---|---|---|
| 严重性 | 🔴 极高 | Agent 进程直接崩溃,DoS 攻击可行 |
| 可利用性 | 🔴 高 | 任何外部输入源(Webhook、用户消息、工具返回)均可触发 |
| 静默性 | 🟡 中 | KeyError 堆栈明确,但上游缺少保护 |
| 影响范围 | 🔴 极广 | 所有使用 BaseMessage.content_blocks 的 Agent |
langchain_core/messages/base.py 中 BaseMessage.content_blocks 属性调用
block_translators/anthropic.py 的 _convert_to_v1_from_anthropic_input() 时,
直接访问嵌套字典键而不校验 key 是否存在,导致畸形 content_blocks 触发未捕获的 KeyError。
Agent 在生产环境中接收外部输入(用户消息、Webhook、工具返回)时,无法控制输入格式,攻击者或错误系统可构造畸形消息实现 拒绝服务攻击(DoS)。
HumanMessage(content=[{"type": "image", "source": {"type": "base64"}}]) KeyError: 'data' ← at block["source"]["data"] # Stack trace: base.py:259 content_blocks anthropic.py:139 _convert_to_v1_from_anthropic_input anthropic.py:108 _iter_blocks → block["source"]["data"] ← 根因
ToolMessage( content=[{"type": "document", "source": {"type": "url"}}], tool_call_id="tool-call-1" ) KeyError: 'url'
SystemMessage(content=[{"type": "document", "source": {"type": "file"}}]) KeyError: 'file_id'
AIMessage(content=[{"type": "document", "source": {"type": "text"}}]) KeyError: 'data'
block_translators/anthropic.py :: _convert_to_v1_from_anthropic_input() │ ├─ _iter_blocks() 函数 │ ├─ case "image" + "base64": block["source"]["data"] ← 无校验 │ ├─ case "document" + "url": block["source"]["url"] ← 无校验 │ ├─ case "document" + "file": block["source"]["file_id"] ← 无校验 │ └─ case "document" + "text": block["source"]["data"] ← 无校验 │ └─ 错误:无 try/except KeyError,无 Schema 预校验 → 任何外部来源传入的畸形 content_block → 未捕获 KeyError → 进程崩溃,Agent 不可用 攻击面: 任何能向 Agent 发送消息的渠道(Webhook / API / 工具返回) × 无需认证 × 无需特殊权限 → 构造畸形 content_block → Agent DoS
from ark_trust import OutputValidator, Schema # 定义 MessageSchema,确保 content_blocks 结构完整 message_schema = Schema( type="object", fields=[ Schema.Field("type", "string", required=True), Schema.Field("source", "object", required=True), ], allow_extra=False ) validator = OutputValidator(schema=message_schema) # 外部消息入队前校验 raw_message = get_external_message() # 来自 Webhook / 用户 / 工具 result = validator.validate(raw_message.content_blocks) if not result.valid: raise ValidationError(f"Malformed content_blocks rejected: {result.errors}") # 进程存活,错误可追踪,不影响其他请求
from ark_trust import CircuitBreaker # 外部输入源连续失败时熔断 breaker = CircuitBreaker( failure_threshold=3, # 3 次 KeyError → 打开 recovery_timeout=60, # 60 秒后尝试半开 ) async def process_external_message(msg): try: blocks = msg.content_blocks # 可能抛 KeyError except KeyError: breaker.record_failure() raise ExternalInputError(msg) # 快速失败,不拖垮 Agent else: breaker.record_success() return blocks # breaker.open() 后,所有外部消息直接拒绝 # 保护 Agent 进程不被外部畸形数据 DoS
from ark_trust import IdempotencyGuard guard = IdempotencyGuard(ttl=300) # 畸形消息被第一次拦截后,相同 key 直接命中缓存 result = guard.execute( key=msg.id, fn=lambda: process_external_message(msg), ) # 第二次相同畸形消息:缓存命中 → 零额外处理 # 防止攻击者重放同一畸形消息消耗资源
| 场景 | 框架现状 | ARK 保护后 |
|---|---|---|
| 畸形 image block | 🔴 进程崩溃 | 🟢 入口处校验失败,错误留痕 |
| 畸形 document block | 🔴 进程崩溃 | 🟢 Schema 校验 + CircuitBreaker 保护 |
| 畸形消息重放 | 🔴 每次都崩溃 | 🟢 IdempotencyGuard 缓存命中 |
| 连续畸形消息 | 🔴 DoS 可行 | 🟢 CircuitBreaker 熔断保护 |
| 错误可追踪性 | 🔴 堆栈分散 | 🟢 OTel Bridge 统一留痕 |
| 字段 | 值 |
|---|---|
| 报告编号 | ark-report-38667-20260724 |
| 上游 Issue | langchain-ai/langchain#38667 |
| 问题类型 | DoS / KeyError / 静默崩溃 |
| 影响版本 | langchain-core 全版本 |
| 报告时间 | 2026-07-24 09:29 CST |
| 诊断者 | ARK Cruise Bot |