🔴 ARK Trust Diagnostic #38667

langchain-core: KeyError DoS via Malformed Content Blocks

langchain-ai/langchain#38667 · 2026-07-05 · bug / core / external · 4 comments
bug core external

🚨 风险定级

维度评级说明
严重性🔴 极高Agent 进程直接崩溃,DoS 攻击可行
可利用性🔴 高任何外部输入源(Webhook、用户消息、工具返回)均可触发
静默性🟡 中KeyError 堆栈明确,但上游缺少保护
影响范围🔴 极广所有使用 BaseMessage.content_blocks 的 Agent

📋 问题概述

langchain_core/messages/base.pyBaseMessage.content_blocks 属性调用 block_translators/anthropic.py_convert_to_v1_from_anthropic_input() 时, 直接访问嵌套字典键而不校验 key 是否存在,导致畸形 content_blocks 触发未捕获的 KeyError

Agent 在生产环境中接收外部输入(用户消息、Webhook、工具返回)时,无法控制输入格式,攻击者或错误系统可构造畸形消息实现 拒绝服务攻击(DoS)

💥 4 种触发路径

路径 1:image block 缺 "data"

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"]  ← 根因

路径 2:document block 缺 "url"

ToolMessage(
    content=[{"type": "document", "source": {"type": "url"}}],
    tool_call_id="tool-call-1"
)
KeyError: 'url'

路径 3:document block 缺 "file_id"

SystemMessage(content=[{"type": "document", "source": {"type": "file"}}])
KeyError: 'file_id'

路径 4:document block 缺 "data"

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

✅ ARK Trust 修复方案

1. OutputValidator — 入口拦截(根本解法)
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}")
    # 进程存活,错误可追踪,不影响其他请求
2. CircuitBreaker — 外部输入源熔断(第二防线)
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
3. IdempotencyGuard — 防止畸形消息重放攻击
from ark_trust import IdempotencyGuard

guard = IdempotencyGuard(ttl=300)

# 畸形消息被第一次拦截后,相同 key 直接命中缓存
result = guard.execute(
    key=msg.id,
    fn=lambda: process_external_message(msg),
)
# 第二次相同畸形消息:缓存命中 → 零额外处理
# 防止攻击者重放同一畸形消息消耗资源

🆚 对比:框架无保护 vs ARK 保护

场景框架现状ARK 保护后
畸形 image block🔴 进程崩溃🟢 入口处校验失败,错误留痕
畸形 document block🔴 进程崩溃🟢 Schema 校验 + CircuitBreaker 保护
畸形消息重放🔴 每次都崩溃🟢 IdempotencyGuard 缓存命中
连续畸形消息🔴 DoS 可行🟢 CircuitBreaker 熔断保护
错误可追踪性🔴 堆栈分散🟢 OTel Bridge 统一留痕

📚 诊断元数据

字段
报告编号ark-report-38667-20260724
上游 Issuelangchain-ai/langchain#38667
问题类型DoS / KeyError / 静默崩溃
影响版本langchain-core 全版本
报告时间2026-07-24 09:29 CST
诊断者ARK Cruise Bot