安全模型
安全模型
本页记录了 Apache Camel 的安全模型:哪些对象是受信任的、信任边界位于何处、什么构成框架漏洞,以及对运维人员和路由作者有哪些要求。它是 Camel PMC 在对安全报告进行分类处理时所采用的参考依据,也是项目在决定某项行为应当在框架层面加固还是由部署方式来解决时所依据的标准。
它对以下两份现有文档作补充:
- Security —— 面向用户的安全功能目录(路由安全、载荷安全、端点与配置安全、保管库、JSSE)。
- 仓库中的
design/security.adoc设计文档 —— 由注解驱动的安全策略执行框架,能够在启动时检测不安全的配置。
有关如何报告漏洞的说明,请参阅 Apache Camel Security 以及仓库中的 SECURITY.md 文件。
受众
本文档面向以下四类读者:
- 安全研究人员与 CVE 报告者,他们需要在提交报告之前了解 Camel PMC 会接受哪些问题作为框架漏洞。
- 自动化分类处理工具(CVE 扫描器、AI 辅助安全审查),它们需要一份权威的范围说明,以便区分真正的框架漏洞与有意为之且已有文档记录的设计选择。
- Camel 提交者与组件作者,他们负责评审拉取请求和编写新组件,需要了解哪些默认值和模式是可接受的。
- 运维人员与部署负责人,他们需要了解如何安全地部署 Camel 应用,以及框架将哪些加固职责交由他们承担。
信任模型
Camel 是一个嵌入到他人应用程序中的集成框架,而不是一个多租户的托管服务。它的信任模型正反映了这一点。
角色
| 角色 | 信任级别 | 该角色可以做什么 |
|---|---|---|
| Camel 提交者与组件作者 | 受信任 | 定义 API、编写组件、选择默认值、发布版本。框架依赖这些贡献者提供安全的默认配置。 |
| 路由编写者(用 Java、XML 或 YAML DSL 编写 Camel 路由的人) | 完全受信任 | 在 .bean()、.process() 和 Class 引用中执行任意 Java 代码;在 simple、groovy、jexl、mvel、xpath、ognl 等表达式中求值任意表达式;访问 classpath 上的任何类;配置任何组件选项。路由编写者执行代码是设计使然,并非框架的漏洞。 |
| 部署运维人员(配置和部署 Camel 应用的人) | 完全受信任 | 设置配置属性(包括密钥)、选择运行时、决定在网络上暴露什么、决定是否启用管理端点、选择 JVM 和操作系统用户,以及配置密钥后端。除非框架的默认设置将其暴露,否则运维人员的错误配置不算是框架漏洞。 |
| 外部消息发送方(HTTP 客户端、JMS 生产者、文件投递者、SMTP 发送方、CoAP 对端、AMQP 发布者、Kafka 生产者、邮件发送方等) | 不受信任 | 通过网络或文件系统向 Camel 路由发送消息。这是主要的攻击者模型。框架自身绝不能把一条不受信任的消息转化为代码执行、文件读取、请求伪造或身份验证绕过。 |
| 组件的远端——路由所访问的远程服务、对象存储、消息代理和 AI 模型 | 持有路由数据方面受信任;对其返回内容不受信任 | 返回的载荷、对象与 blob 名称、远程文件名、列表条目及其他元数据,以及(对于 AI 组件)生成的文本和工具调用参数。是运维人员选择了与这些服务通信,因此连接本身是受信任的;但当更广泛的一组主体可以向存储写入内容或影响提示词时,它们返回的字符串就受到攻击者影响。参见对手模型。 |
信任边界
Camel 中最基本的信任边界位于路由(以及运维人员配置的一切)与流经路由的数据之间。凡是路由作者编写的代码都是受信任的代码;而任何来自 Camel 消费者、出现在 Exchange 正文、头部或附件中的内容都是不受信任的数据。
框架的职责就是维护这条边界的完整性:不受信任的数据不得变成代码,不得将路由重定向到其他端点,不得被反序列化为任意类型,也不得以解析远程资源的方式进行解析——除非路由作者明确要求如此。
攻击者模型
框架所防御的攻击者,即上文《角色》中所指的外部消息发送者角色:某个网络或文件系统对端,将消息放入 Camel 消费者读取的传输通道中。本小节说明下方适用与不适用规则所假定的攻击者形态,以便安全报告能够按照编写这些规则时所依据的同一模型进行评估。
攻击者可控的内容: 到达消费者读取的输入端的消息正文、头部、附件和传输元数据,以及在协议限制范围内任意重放或构造该消息的能力。攻击者可能将上述任意组合用于攻击框架自身的内部机制——表达式语言、类型转换器、Exchange / Message 模型、头部命名空间、EIP 处理器、属性占位符与 Bean 引用解析,以及消费者或数据格式所使用的任何默认解析器配置。
另有三类输入也视为攻击者可控,尽管它们并非以消息形式到达消费者读取的传输通道。每一类都曾产生过被接受的安全通告,并且每一类都容易被误认为受信任数据,因为它们来自运维人员配置的服务,而非直接来自网络传输:
- 远程后端服务回报的名称与元数据。 对象键、blob 与存储桶名称、远程文件名和列表条目由任何能向该存储写入的人来决定,而这些人通常是一个比能访问到该路由的对端更宽泛的主体集合。若某个组件用这样的名称拼接本地路径、命令参数或报头,那么它处理的就是不可信输入(CVE-2026-60093
camel-azure-storage-datalake、CVE-2026-66906camel-azure-storage-blob、CVE-2026-66907camel-google-storage—— 远程对象名逃逸出所配置的下载目录)。这与运维人员为路由自身使用而预置的**状态存储的「内容」**不同,框架确实假定后者是可信的;参见 已知限制 中关于聚合仓储(aggregation repository)的条目。 - 大语言模型的输出。 在 AI 组件中,模型的回复——包括工具调用的字段名和参数——是由提示词以及外部方通常能够影响的检索上下文生成的。模型输出属于不可信输入,而不是可信的控制通道;若某个组件将其映射到
Exchange报头映射或映射到派发决策,它就要遵守与任何其他入站映射点相同的规则(CVE-2026-49042camel-langchain4j-tools:未经过滤的工具调用参数名变成了任意Exchange报头)。 - 并非消息报头的传输元数据。 查询参数、路径段、订阅与主题名称以及连接属性,与报头一样通过相同的映射代码进入
Exchange(CVE-2026-55993camel-atmosphere-websocket:WebSocket 查询参数未经过HeaderFilterStrategy映射)。
攻击者试图做什么: 破坏下方 安全属性与违规严重程度 或 核心路由引擎不变量 中列出的某项属性——将不可信输入转化为代码执行、任意文件读写、请求伪造、非预期的端点或 bean 派发、反序列化利用链(gadget)、认证或授权绕过,或机密与 Exchange 状态的泄露。
不假定攻击者拥有的能力: 在运行 Camel 上下文的 JVM 内部执行代码(那属于路由作者的领域)、运维人员的文件系统、部署的配置来源、密钥库(secrets vault)、管理网络、回连 broker / SDK / 端点的连接,以及路由作者和运维人员所配置的密钥与凭据。他们无法编写或修改路由定义、配置或运行时镜像。他们也无法通过成为 JVM 中的同租户来绕过信任边界;Camel 不是沙箱,也不会假装是沙箱(参见下方 未提供的安全属性)。
以下行为者明确不在对抗者模型之内。若某份报告要求其中之一个作为攻击者,则该报告为 OUT-OF-MODEL: adversary-not-in-scope(参见 分诊处置)。
- 路由作者。 路由作者将攻击者可控的头信息作为
simple、OGNL、bean 或脚本表达式进行求值,编写的是如实表达其意图的受信任代码。只有当框架在路由作者并未要求的情况下,将不可信输入传给求值器时,框架才属于讨论范围(参见不在范围之内中的路由作者条目)。 - 部署运维人员。 关闭 TLS 校验、启用 Java 序列化、选择宽松配置文件,或将管理界面对外暴露的运维人员,需要自行承担由此带来的后果。配置错误属于运维人员的范畴,除非该默认配置是由框架自身引入的。
- 访问管理界面的网络对端。
camel-management、开发者控制台、camel-jolokia和 JMX 属于管理类 API,其信任边界是管理界面本身(JVM 的 JMX 认证、Jolokia 限制器策略、管理端口的网络暴露范围),而非单个 MBean 方法。参见不在范围之内中的管理界面条目。 - 传递性第三方依赖的作者。 如果某个 JAR 被 Camel 引入,但其漏洞无法通过任何 Camel 暴露的代码路径被触及,则该 CVE 属于上游项目的漏洞。参见不在范围之内中的第三方依赖条目。
漏洞范围
如果一份报告证明了框架在默认配置或合理预期的配置下,会让不可信输入越过信任模型认为不应被越过的信任边界,则该报告属于范围之内。
本模型涵盖哪些构件。 本文档描述的是从 apache/camel 仓库发布的构件——camel-core、各组件、各 DSL 以及 Camel CLI。同级子项目有各自独立的发布节奏,并按照各自的范围进行分类:Camel K、Camel Quarkus、Camel Spring Boot、Camel Kafka Connector 和 Camel Karaf。对于这些子项目所嵌入的核心路由行为,它们继承本信任模型,但每个子项目还增加了各自的部署面,具有本页面未描述的角色与威胁方——CVE-2026-45760,即 Camel K 中的跨命名空间构建"代理"攻击,就是一个典型例子,其完整机制(Kubernetes 命名空间、Operator RBAC)完全存在于本模型之外。针对这些子项目的报告仍由同一个 PMC 在同一个私有邮件列表中分类处理,但依据的是子项目的暴露面,而非本页面所描述的暴露面。
安全属性与违规严重性
上面的信任边界声明对框架提出了一小部分具体属性的承诺。每一项属性都对应着一旦框架未能维持该属性时攻击者所能达成的特定影响,以及一个指示性的严重程度等级。下方纳入范围的漏洞类别中的类别是破坏这些属性的机制;此处的表格则是影响视图,可供分诊工具和报告者用来评估候选发现的严重程度及其破坏了哪一项防护属性。
| 框架针对不可信输入所维护的属性(默认或合理预期的配置下) | 违规时的表现(报告者或扫描器观察到的症状) | 指示性严重程度 |
|---|---|---|
| 不可信数据绝不会被转换为可执行代码或操作系统命令 | 精心构造的消息、报头或附件触发反序列化 gadget 链、Bean/方法/命令分发、路由作者从未请求过的表达式/模板求值,或被拼接进组件启动的外部进程的参数向量中 | 严重(CVSS 9.0-10.0) |
| 不可信数据无法将路由重定向到不同的端点、Bean、方法或命令 | 从网络注入的控制报头改变了 Exchange 的分发目标、所执行的操作,或所使用的传输方式与凭据——无论它位于内部命名空间内(CamelBeanMethodName、CamelExecCommandExecutable、CamelHttpUri、CamelJmsDestinationName …)还是命名空间之外(websocket.connectionKey、gridfs.*、irc.sendTo、operationName、mail.smtp.* …) |
严重(CVSS 9.0-9.8) |
| 不可信数据绝不会被反序列化为任意 Java 类型 | 消费者、类型转换器或持久化状态仓库在没有有效过滤器的情况下,通过 ObjectInputStream/XStream/Hessian/多态 Jackson 实例化攻击者选定的类 |
可触达 gadget 时为严重(9.0-9.8);否则为高危(7.0-8.6) |
| 不可信解析不会解析外部或远程资源 | 对攻击者输入的 XML/XSLT/XSD/XPath 解析默认会读取本地文件、执行 SSRF,或抓取远程 DTD 或样式表 | 高危(CVSS 7.5-8.6);若导致 RCE 或凭据窃取则为严重 |
| 不可信文件名或 URI 组件无法逃逸已配置的根目录 | 文件/邮件/FTP/对象存储的消费者或生产者通过 ../ 或绝对路径读写配置目录之外的路径,无论该名称是通过报头传入还是由远程存储回传 |
高危(CVSS 7.5-8.8) |
| 宣称提供认证或授权的组件确实会强制执行它们 | 请求在没有有效令牌、未经校验的签发者/受众/签名、或在认证处理程序本应覆盖的子路径上被放行——因为相关选项未配置时某项检查被静默跳过,或因为授权决策是基于与分发决策所用规范化方式不同的值计算得出的 | 严重(CVSS 9.0-9.8) |
| 机密信息与内部 Exchange 状态不会被泄露 | 凭据、消息体或配置值出现在日志、事件、全局可读文件,或权限较低方可见的 HTTP 响应中 | 中危至高危(CVSS 5.3-8.2),取决于泄露的内容 |
| 不可信输入不会被拼接进 Camel 构建的后端查询语言 | Camel 构造了 Cypher/XSLT 扩展/类似的查询,而攻击者改动了其结构而非仅仅是其数据 | 高危至严重(CVSS 8.1-9.8) |
| 以上全部属性在零安全配置下均成立 | 上述任意一项仅凭将组件加入路由并发送消息即可触发,无需显式设置任何有风险的选项 | 取决于底层漏洞类别;始终在范围内 |
上述层级是指示性的,反映 Camel PMC 历来对这些类别的评分方式。PMC 会根据每份报告的攻击向量、抵达该代码路径所需的配置,以及所展示的具体影响,为其指定最终的 CVSS 向量。需要非常规非默认配置才能触发的发现,或影响有限的发现,其评分可能低于该层级所暗示的水平;而能够进一步串联直至完全控制主机的发现,评分则可能更高。
核心路由引擎不变式
上表是从跨组件影响角度的视图:每项属性都是在某个组件于数据进入路由的过程中未正确处理不可信输入时遭到破坏的。本小节给出与之互补的引擎视角——即 camel-core 自身(路由引擎、Exchange / Message 模型、EIP 处理器、表达式、语言与属性占位符解析,以及类型转换器和数据格式注册表)独立于任何单个组件所维护的保证。之所以列出这些内容,是为了让定位在 core/camel-* 模块(而非某个组件)中的候选项,能够直接归入相应的属性与处置结论,而无需重新推导信任模型。
这些并非新增承诺。每条不变式都是下文范围内的漏洞类别或信任模型中信任边界在引擎层的投影;之所以在此重述,是因为针对核心的发现是针对核心代码报告的,而分类处理者需要核心侧的表述来做出判定。
| 路由引擎自行维护的不变式(不涉及特定组件的配置) | 违反该不变式时的表现 | 指示性严重程度 |
|---|---|---|
除非路由作者在路由的某个位置放置了表达式或谓词,否则引擎绝不会将 Exchange 的消息体、头或属性作为 simple、OGNL、bean 或脚本表达式进行求值 | 某个核心处理器或语言将不可信的消息内容作为表达式解析,而没有路由作者编写的表达式引用它 | 严重(CVSS 9.0-9.8) |
不可信的 Exchange 内容不会通过引擎自身的动作来选择所分发的端点、bean、方法或命令;toD、recipientList、routingSlip、动态路由器以及 bean 方法解析的动态目标,仅由路由作者的表达式和文档中记载的分发头计算得出 | 引擎自身将消息体或附件中的值提升(promote)到了分发头(CamelBeanMethodName、CamelHttpUri、CamelJmsDestinationName……)或动态目标表达式输入之中 | 严重(CVSS 9.0-9.8) |
当路由仅声明目标类型(convertBodyTo、带类型的 message body、表达式强制类型转换)时,核心类型转换注册表不会实例化或反序列化攻击者选择的 Java 类型;读取外部实体或运行 ObjectInputStream 的转换器属于执行转换的组件自身的职责,而非核心的自动行为 | 已注册的核心转换器在自动转换过程中,从不可信的消息体实例化或反序列化任意类型(历史案例:CVE-2015-0263,camel-core 的 XML 转换器) | 可触达利用链(gadget)时为严重(9.0-9.8);否则为高危(7.0-8.6) |
属性占位符与 bean 引用解析({{…}}、#bean:、#class:、#type:、#property:)作用于路由作者或运维人员提供的路由与配置文本,绝不作用于 Exchange 内容 | 消息体或头的内容进入到占位符或 #class: / #bean: 解析流程,并被解析或实例化 | 严重(CVSS 9.0-9.8) |
引擎与 Exchange / Message 模型绝不将消息体字段、附件或传输元数据提升到内部 Camel* 头命名空间;由不可信的线路输入填充该命名空间是 消费者 的职责,受入站 HeaderFilterStrategy 约束(CVE-2025-27636 系列),而非引擎的动作 | 核心机制(而非某个特定消费者)将不可信来源的值复制到了内部头命名空间 | 严重(CVSS 9.0-9.8) |
错误处理、死信路由、重新投递以及带内(in-band)跟踪/调试处理器,在带内路由路径上不会将不可信内容作为代码求值,也不会将某个 Exchange 的消息体、头或机密暴露给带内路径上的无特权参与方 | onException、死信或 BacklogTracer 的带内路径将不可信内容转化为求值行为或跨 Exchange 泄露。通过管理连接(JMX、Jolokia、开发者控制台)达成的暴露或表达式求值,由 不在范围之内(Out of scope)部分中的管理界面条目所约束,而非受本不变式约束 | 中等至严重,取决于可触达的内容 |
| 引擎不提供任何无界资源方面的保证 | 在攻击者可影响的流量下出现不受限的路由、无界的聚合或递归。这是一个由运维人员限定的可用性问题(throttle、circuitBreaker、resilience4j、JVM 限制);参见 不在范围之内(Out of scope)。唯一影响是资源消耗的核心发现会被关闭为 not a vulnerability | 不在范围之内(无引擎层面保证) |
位于 core/camel-* 模块中的候选项,首先依据上述这些不变式来判定。如果引擎确实维持了该不变式,而违规仅因路由编写者在不可信输入之上编写了表达式或路由,或者未使用 removeHeaders("Camel*") 就将不可信源直接接入,那么其归属应按 超出范围 中「路由编写者立场」来处理,而非框架漏洞——这与本模型其余部分在「路由及其配置」与「流经其中的数据」之间所划的界线是一致的。
未提供的安全属性
上述 安全属性与违规严重性 以及 核心路由器引擎不变式 的补集:即框架不主张的属性,以及框架本身不防御的已知攻击类别。列出这些内容,才能让下面的「范围内 / 范围外」规则构成一个封闭集合,而不是被解读为「其余一切都算漏洞」。如此一来,某份报告的全部主张若只是「功能 X 未能做到 Y」,便可以按「X 本来就不为 Y 而设计」来归类,而无需逐案再三辩论。
不对路由或运行它的 JVM 进行沙箱隔离。 路由作者可以在
.bean()、.process()和类引用中执行任意 Java 代码;在simple、groovy、jexl、mvel、xpath、ognl中求值任意表达式;访问类路径上的任何类;并配置任何组件选项。Camel 不会限制路由代码被允许做什么(参见 Roles 中的路由作者条目)。在攻击者可影响的流量量级或资源开销下,不提供可用性保证。 引擎不会限流,不会限制聚合规模,不会对递归设上限,也不会限制单个
Exchange的内存占用。由运维人员自行施加throttle、circuitBreaker、resilience4j以及 JVM 层面的限制;第三方解析器中的算法复杂度攻击(XML billion-laughs、路由作者所写正则的 ReDoS、zip / gzip / brotli 输入的解压放大攻击)不在范围内,除非 Camel 暴露该解析器的方式绕过了库自身的限制。参见 Out of scope 中的拒绝服务条目以及 Core router-engine invariants 中的无界资源行。不会自动净化应用级语义头部。 框架的自动头部过滤仅作用于内部的
Camel*命名空间(不区分大小写匹配,因此Camel、CAMEL和caMEL均被覆盖)。组件在其文档化的头部契约中所消费的应用级头部——camel-mail中的To、Cc、Bcc、Subject、From;任意 HTTP 头部名称;JMS 属性;AMQP、MQTT、CoAP 和 Kafka 头部——都是有意透传的。针对不受信任的上游对这些头部进行净化是路由作者在信任边界上的职责(removeHeaders、规范化、允许列表)。本免责声明涵盖组件作为载荷数据读取的头部;但不涵盖组件自身的控制头部——即那些用于选择目标、操作或传输方式及其凭据的头部——无论这些头部叫什么名字,过滤它们都是框架的职责。参见 Known limitations 下的第三个项目符号,以及 In-scope vulnerability classes 中 Camel-header 类下的控制头部定义。不抵御传递性依赖的 CVE。 Camel 引入的 JAR 中出现的 CVE 属于上游项目的漏洞;Camel 修复的是 Camel 代码中的 CVE,而非第三方 JAR 中的 CVE。Camel 可能会升级依赖以获取上游修复,但 CVE 本身是针对上游项目来关闭的。参见 Out of scope 中的第三方依赖条目。
在
dev或test配置下不提供生产环境保证。 在需选择启用的dev配置下,开发控制台、调试与跟踪端点、积压调试器(backlog debugger)以及详细诊断均被启用,且insecure:dev策略被放宽为allow。Camel 可能会暴露在prod部署中不会暴露的配置、路由和Exchange细节。框架默认不应用任何配置(安全策略为warn);必须显式选择prod才能将策略升级为fail。参见 Out of scope 中的配置条目、Configuration variants that change the model 以及design/security.adoc。在非默认的诊断日志级别下,不提供生产级信息隐藏保证。 DEBUG 和 TRACE 日志级别属于诊断配置而非生产配置;它们预期会记录默认的 INFO、WARN 和 ERROR 级别不会记录的内部
Exchange、路由和配置细节。项目力求在合理的范围内即使在诊断级别也不记录敏感数据,但不承诺对其进行脱敏。框架承诺保持不含敏感数据的是默认的 INFO、WARN 和 ERROR 级别;参见 In-scope vulnerability classes 下的机密或敏感 Exchange 状态的信息泄露类别。不防范运维人员在框架默认值之外错误配置部署。
trustAllCertificates=true、hostnameVerificationEnabled=false、allowJavaSerializedObject=true、transferException=true、将管理界面暴露在公网中、将聚合仓库存储放在可写共享上——这些都是运维人员的决定。只有当默认配置本身带有风险行为时,框架才在范围内。参见 Out of scope 中的显式选择启用条目。不提供常数时间、抗侧信道的比较或密码学原语。 头部、令牌和标识符的相等性比较使用的是通用 Java 比较。将共享密钥与不受信任的输入进行比较的路由作者代码有责任使用常数时间比较器;Camel 不提供这样的比较器。
易混淆特性
有些特性看起来像安全属性,却常被误认为安全属性。下面逐一说明,以便让那些建立在误解之上的报告能依据正确的契约予以关闭。
- **
DefaultHeaderFilterStrategy是内部命名空间过滤器,而不是应用层请求头清洗器。**它以不区分大小写的方式过滤Camel*命名空间(Camel、CAMEL和caMEL一视同仁),而这正是内部派发一族(即 CVE-2025-27636 这一类问题)的所在。它不会、也无法剥离组件作为语义输入读取的应用层请求头。需要应用层请求头清洗的路由作者必须在信任边界处显式完成这一操作。 - **
removeHeaders("Camel*")剥离的是内部派发请求头,而不是所有不可信来源的请求头。*它是针对内部请求头派发这一类问题(参见部署加固*)在信任边界上的推荐做法,也是必要的;但它本身并不足以清洗下游组件将会信任的应用请求头。它同样无法匹配写在命名空间之外的控制请求头——websocket.connectionKey、gridfs.*、irc.sendTo、operationName、mail.smtp.*。这些请求头的过滤属于框架的职责,凡是可以被触及之处都已作为安全公告予以修复;但如果某条路由运行在早于相应修复的版本上,就需要额外显式剥离该命名空间。 - **安全策略强制框架是配置检查器,而非运行时沙箱。**四类检查(
secret、insecure:ssl、insecure:serialization、insecure:dev)会在启动阶段检测不安全的配置,并在prod配置下发出警告或导致启动失败。它们不会拦截运行时数据,也不会按单个Exchange强制执行策略。参见design/security.adoc。 - **组件标记为弃用并不是安全边界。*标记为
(deprecated)的组件仍会随受支持的版本发布,并继续属于有限维护范围(参见已弃用与已移除的组件*)。弃用意味着存在一条附有迁移文档的移除路径;它本身并不会缩小信任边界,也不意味着该组件不适合接收修复补丁。 - **默认使用 TLS 并不等于对端身份认证。*默认以 TLS 传输的组件(HTTP、AMQP、MQTT、Kafka、JMS)可以保护通信线路免受被动窃听和简单中间人攻击。但它们本身并不能验证对端就是路由期望通信的对象;这需要运维人员配置带信任库和主机名校验的
SSLContextParameters(参见部署加固*)。
纳入范围的漏洞类别
以下类别源自 Apache Camel PMC 历史上已受理的漏洞公告。每一项中的 CVE 编号仅为代表性示例,并非完整清单。完整的公告历史见 /security/。
不可信输入的不安全反序列化
任何将外部生产者发来的数据直接传递给 ObjectInputStream.readObject()、XStream / Hessian / Castor / SnakeYAML 反序列化器,或未经有效过滤器或允许列表限制的 Jackson 多态读取器的代码路径。
历史示例:
- CVE-2015-5344(
camel-xstream)、CVE-2017-3159(camel-snakeyaml)、CVE-2017-12633(camel-hessian)、CVE-2017-12634(camel-castor)— 数据格式组件对不可信类型执行反序列化。 - CVE-2016-8749(
camel-jackson)— 攻击者可控的CamelJacksonUnmarshalType头部用于选择反序列化类型。 - CVE-2015-5348(
camel-jetty、camel-servlet)— HTTP 消费者自动识别application/x-java-serialized-object并对消息体进行反序列化。 - CVE-2020-11972(
camel-rabbitmq)、CVE-2020-11973(camel-netty)— 默认消费者配置中启用了 Java 反序列化。 - CVE-2024-22369(
camel-sql)、CVE-2024-23114(camel-cassandraql)、CVE-2026-25747(camel-leveldb)、CVE-2026-27172(camel-consul)、CVE-2026-40858(camel-infinispan)— 聚合仓库对持久化状态直接调用ObjectInputStream.readObject()。 - CVE-2026-40048(
camel-pqc)— 基于文件的密钥存储对.key文件执行反序列化。 - CVE-2026-40473(
camel-mina)— TCP/UDP 类型转换器将接收到的字节包装进ObjectInputStream。 - CVE-2026-40860(
camel-jms、camel-sjms、camel-sjms2、camel-amqp)— 在mapJmsMessage=true(默认值)时,JmsBinding.extractBodyFromJms()调用ObjectMessage.getObject()而未施加任何过滤器。 - CVE-2026-43866(
camel-jms、camel-sjms、camel-sjms2)— 通过 JMSObjectMessage携带伪造的DefaultExchangeHolder,绕过为 CVE-2026-40860 添加的ObjectInputFilter(一次绕过过滤器的后续漏洞)。 - CVE-2026-40859(
camel-vertx-http、camel-netty-http)— 对 HTTP 响应体直接使用原始ObjectInputStream进行反序列化。 - CVE-2026-43865(
camel-hazelcast)— 默认配置的受管 Hazelcast 实例中存在不安全的 Java 反序列化(同样属于不安全默认配置的情形)。 - CVE-2026-46590、CVE-2026-43867(
camel-pqc)— HashiCorp Vault 和 AWS Secrets Manager 的密钥生命周期管理器使用ObjectInputStream对持久化的密钥元数据进行反序列化(为 CVE-2026-40048 的后续漏洞)。 - CVE-2026-42527 — 过滤器本身过于宽松:默认的
ObjectInputFilter模式允许java.net.**,因而导致基于 DNS 的信息泄露。存在但强度不足的缓解措施本身就属于此类问题;参见分类处置下的修复不完整说明。
自 4.22 起(CAMEL-24296),CamelObjectInputStream 默认会安装一个 JEP-290 ObjectInputFilter:当运维人员设置了 JVM 级别的 jdk.serialFilter 时会遵循该过滤器,否则应用 Camel 自身的允许列表。这是位于上述各组件规则之下的纵深防御措施,并非对其的替代:它只约束经过该类的流,而某个自行构造原始 ObjectInputStream 的组件,或通过第三方序列化器 API 间接使用 JDK 序列化机制的组件,仍然要为自身负责配置过滤器。
XML 外部实体(XXE)与远程 DTD/样式表解析
任何在默认情况下会解析外部实体,或从不可信输入中抓取远程 DTD / 样式表的 XML 解析器、XSLT 引擎、XSD 校验器、XPath 求值器或 XML 数据转换器。
历史案例:CVE-2014-0002 和 CVE-2014-0003(camel-xslt)、CVE-2015-0263(camel-core 中的 XML 转换器)、CVE-2015-0264(camel-core 中的 XPath 语言)、CVE-2017-5643(Validation 组件)、CVE-2018-8027(XSD 校验处理器)、CVE-2019-0188(camel-xmljson 经由 json-lib)。
表达式或模板语言注入
任何在路由编写者未显式声明授权的情况下,将不可信输入作为 Camel simple 表达式或模板语言(Velocity、Freemarker、Mustache、MVEL 等)进行求值的代码路径。
历史案例:CVE-2013-4330(camel-file / camel-ftp 中生产者将 CamelFileName 头部的值传给 simple)、CVE-2020-11994(模板组件中的模板注入加任意文件泄露)。
编写 .simple("${header.x}") 路由并针对攻击者可控头部的路由编写者确实是在注入代码,但框架无法代替他们判断 header.x 是否可信。这种情况属于路由编写者的责任,而非框架漏洞。属于本范围的情形是:框架自身在路由编写者并未要求的情况下,将不可信输入传递给求值器。 |
|---|
路径穿越
任何让不可信的文件名、头部或 URI 组件导航到所配置根目录之外的消费者或生产者。
历史案例:CVE-2018-8041(camel-mail)、CVE-2019-0194(camel-file)。
名称不一定要出现在消息中。2026 年的一批安全公告源于下载路径,这类路径依据远端存储返回的名称在本地构建目标文件——CVE-2026-66906(camel-azure-storage-blob,downloadBlobToFile)、CVE-2026-60093(camel-azure-storage-datalake,downloadToFile)以及 CVE-2026-66907(camel-google-storage,其中 downloadFileName 使用了 ${file:name} 标记求值,该标记原样返回远端名称,而 ${file:onlyname} 会剥离路径)。在这几种情况下,组件都把配置目录与远端名称拼接起来,然后将结果直接传给 SDK,既没有进行词法规范化,也没有做包含性检查。只要能够向存储写入的主体位于路由的信任边界之外(参见对手模型),对象和 Blob 名称就会受到攻击者影响,因此下载目标必须先经过规范化并验证其解析结果位于配置目录之内,才能被使用。
由解析触发的 SSRF 或远端资源抓取
任何在其默认解析行为中,会依据不可信输入解析 URL 或 DTD 引用的解析器。
历史案例:CVE-2017-5643(Validation 组件抓取远端 DTD)。
Camel 通过消息头来驱动组件行为,例如 CamelBeanMethodName、CamelFileName、CamelExecCommandExecutable、CamelJmsDestinationName、CamelHttpUri、CamelJacksonUnmarshalType 等。任何将不可信输入映射到 Exchange 消息头映射中、却没有采用严格且不区分大小写的 HeaderFilterStrategy 的代码,都会成为这些消息头的注入向量。
历史案例:CVE-2025-27636、CVE-2025-29891(默认 HTTP HeaderFilterStrategy 被绕过)、CVE-2025-30177(camel-undertow 入站过滤)、CVE-2026-33453(camel-coap)、CVE-2026-33454(camel-mail)、CVE-2026-40453(camel-jms、camel-sjms、camel-coap、camel-google-pubsub 的大小写变体后续问题)。此类问题在 2026 年以两种形式反复出现——消费者在没有有效 HeaderFilterStrategy 的情况下映射入站消息头(CVE-2026-46456 camel-aws2-sqs、CVE-2026-46457 camel-nats、CVE-2026-46726 camel-vertx-websocket),以及其非 Camel 前缀的消息头常量绕过 HTTP 消息头过滤器的组件(CVE-2026-46585 camel-lucene、CVE-2026-48203 camel-solr、CVE-2026-48205 camel-dns、CVE-2026-48206 camel-jira、CVE-2026-49098 camel-kafka、CVE-2026-49099 camel-salesforce 等)。正是这种反复出现的问题,促使我们把默认的 Camel* 过滤集中到 DefaultHeaderFilterStrategy 中(CAMEL-23543,Camel 4.21),使消费者和生产者无需各自编写样板代码即可拦截该内部命名空间。
有三项细化决定了这个类的实际适用范围:哪些头部算数、哪些代码位置算数,以及本该挡在中间的过滤器是否真的挡在了中间。每一项都源自某次安全通告,其中若采用更狭窄的解读,都会错误地关闭一个真实的问题。
控制头部由其作用决定,而非其前缀决定。 框架的自动过滤器覆盖 Camel* 命名空间,但这个类所保护的属性是:不可信输入不得操纵交换(exchange)。而组件完全可以随意命名其操纵头部。一个头部只要是控制头部,无论叫什么名字,都应纳入该组件的入站过滤集合,当它选择了以下任一项时:
- 目标——消息发往哪个对端、通道、目的地、主题或接收方(CVE-2026-71300
camel-atmosphere-websocket、websocket.connectionKey/.list/sendToAll;CVE-2026-49097camel-irc、irc.sendTo); - 操作——组件执行哪个方法、动词或命令(CVE-2026-48204
camel-mongodb-gridfs、gridfs.*,包括文件删除;CVE-2026-46592camel-cxf、operationName/operationNamespace;CVE-2026-46587camel-couchbase、CVE-2026-46588camel-couchdb、CVE-2026-46453camel-elasticsearch-rest-client); - 传输或其凭据——组件使用哪个主机、协议、TLS 状态或认证方式(CVE-2026-46584
camel-mail,攻击者提供的mail.smtp.*/mail.smtps.*头部被作为 JavaMail 会话属性应用,削弱了 SMTP 传输安全性,并且在 4.19.0 之前会重定向连接并泄露已配置的凭据)。
相比之下,语义头部是组件将其读作负载数据的头部——To、Cc、Subject、HTTP 的 X- 头部、JMS 属性。这些按契约是透传的,对其做净化是路由作者的工作(参见已知限制)。这两个类别并非由拼写方式区分,因此"该头部没有 Camel 前缀"本身并不能驳回一份报告;分类人员必须追问该头部的作用。某个消费者将不可信输入复制进一个生产者侧视为控制输入的头部,即使两端位于不同组件,也属于同一个问题(CVE-2026-49086 camel-dapr,其中 Pub/Sub 消费者将入站 CloudEvent 的 pub/sub 名称和主题复制进生产者方向的路由头部,使得任何能向已订阅主题发布消息的人都能重定向重新发布的消息)。
每一个入站映射位置都在范围内,而不仅仅是消费者。 Exchange 头部映射由不止一处填充,而每一处都需要一个有效的策略:
- 消费者(Consumers),映射传输层头部——原始形态。
- 数据格式与解组器,映射其解码载荷内部发现的头部。CVE-2026-59230(
camel-mail)是参考案例:MimeMultipart数据格式在headersInline=true时,把被解组消息的 MIME 头部毫无过滤地复制到Exchange上。CAMEL-24419 随后展示了这一教训的另一半——该数据格式配置的是一个普通的DefaultHeaderFilterStrategy,它只识别Camel*/camel*,因此 消费者 路径刻意过滤的mail.smtp.*命名空间仍然得以经由解组路径放行。如果一个入口点过滤的命名空间比其同类入口点更窄,那就是漏洞,而不是配置上的差异。 - 结构化内容模式,即从消息体中解析出的字段成为头部。CVE-2026-63621(
camel-knative)是参考案例:二进制模式下 CloudEvent 属性以 HTTP 头部的形式到达,并经过HeaderFilterStrategy处理;而在结构化模式下,事件是消息体中的一份 JSON 文档,发送方选定的扩展属性被直接映射到消息上。一个组件若过滤了某一种内容模式,就必须过滤所有会到达同一头部映射的内容模式。 - 并非头部的传输元数据——查询参数、路径片段、订阅名称(CVE-2026-55993
camel-atmosphere-websocket)。
从未被调用过的过滤器不算过滤器。 CVE-2026-78329(camel-undertow)是参考案例:UndertowEndpoint 将其 headerFilterStrategy 字段默认设为基类 HttpHeaderFilterStrategy,并把这个实例推入其惰性创建的 HTTP 绑定中,覆盖了绑定在自身构造函数中安装的组件专用 UndertowHeaderFilterStrategy。正确的策略被构造出来,却立刻被替换掉,因此在通过端点配置的路由上它从未运行过——它所携带的早期加固措施(CAMEL-23588)自发布之日起就一直是失效的。同样的形态也出现在头部过滤之外:在 CAMEL-24412 中,为 camel-netty-http 安全约束把关的一个大小写不敏感比较,被置于一个大小写敏感的 startsWith 之后,因此它永远无法改变结果。源码中存在一项防御措施,并不能证明它会执行;报告者和分类处理者都必须确认该守卫位于生效路径之上。
基于 API 的组件的前缀头 —— CamelFhir.*、CamelBox.*、CamelOlingo4.*、CamelAs2.*,以及其他由 camel-api-component 生成的、用于选择 API 方法及其参数的生产者 —— 位于 Camel* 命名空间内,因此完全受该规则约束。所以,对于来自不可信源的 Camel<Api>.* 头到达 API 生产者这一情况,项目的态度是有条件的,而这个条件在于入站消费者,而不在于 API 生产者;并不是"永远不在范围内"。如果某个消费者允许来自不可信源的 Camel<Api>.* 头通过,却没有有效的、不区分大小写的 Camel* HeaderFilterStrategy,那么无论最终消费该头的是哪个生产者,它都在范围内 —— 这与 CVE-2025-27636 一族属于同一类问题。而 API 生产者遵守一个 Camel<Api>.* 头,如果该头之所以到达生产者,只是因为路由作者在入站过滤器存在且有效的情况下,仍将不可信源直接连接到生产者且没有使用 removeHeaders("Camel*"),那么这就是已文档化的 bean 分发约定(见 已知限制),而非框架漏洞。
安全提供组件中的认证或授权绕过
明确提供认证、授权或租户隔离的组件(Keycloak、JWT、Shiro、Spring Security、platform-http 认证处理器等)必须强制执行它们所声称要强制执行的内容。
历史案例:CVE-2026-23552(camel-keycloak 未针对配置的 realm 校验 JWT iss 声明)、CVE-2026-40022(camel-platform-http-main 的 Vert.x 子路由挂载在 <path>* 上,而认证处理器位于精确路径上,从而暴露了 /api、/admin、/observe/info 的子路径)、CVE-2026-46455(camel-keycloak 缺少令牌 IS_ACTIVE 检查,因而过期的访问令牌也会被接受)以及 CVE-2026-53913(camel-keycloak 默认放行:Bearer 令牌仅在角色和权限检查内部才被验证,因此既未配置角色也未配置权限的部署会以未认证状态接受请求)。
以下两条子规则各自都已导致多份安全通告,因此在此明确列出,因为某个组件可能在字面上满足其选项名称,却违反其中任意一条:
未配置的检查必须失败关闭,而不是消失。 CVE-2026-66908(
camel-platform-http-main)是典型案例:当jwtIssuer和jwtAudience都未配置时,代码仅凭密钥库构建JWTAuth实例,因此入站令牌只校验签名和有效期,iss与aud声明根本未被验证——而且这一切悄无声息,服务器照常启动,并报告认证已启用。上文 CVE-2026-53913 以及 CAMEL-24411 也是同样的形态:camel-oauth处理器在不认证调用方的路径上正常返回,于是路由的其余部分继续执行,覆盖了处理器刚刚准备好的挑战。一个无法执行其宣称检查的安全组件,必须拒绝启动或拒绝请求;省略检查并不是中立的默认行为。授权决策与实际执行的操作必须基于同一个值计算。 CVE-2026-40022(
camel-platform-http-main)把 Vert.x 子路由挂载在<path>*上,而认证处理器位于精确路径,因此/api、/admin和/observe/info的子路径会被派发却不受保护。CAMEL-24412 是规范化层面的变体:camel-netty-http在评估安全约束之前,使用区分大小写的startsWith剥离端点的 context-path,而派发时则以不区分大小写的方式匹配路径——于是 context-path 仅大小写不同的请求能够进入路由,却按未剥离的目标进行评估,匹配不到任何包含规则,而未匹配的目标被算作不受限制。凡是路由与授权各自都要对路径、主机或标识符做规范化的地方,两者必须以完全相同的方式规范化;哪怕两边各自都正确,只要存在差异,就构成认证绕过。这种差异同样会出现在授权之外,而协议决定了它的严重程度。当协议不区分大小写而比较却区分大小写时,改动大小写即可绕过比较——若协议在传输线上就已规范化,比较甚至可能永远匹配不上:HTTP/2 要求标头名称全为小写,因此在那里区分大小写的标头检查不仅仅是可被绕过,而是根本不存在。应在组件支持的每一种协议版本下测试同一道防线。前缀变体是同一种错误的另一种形态:通过判断配置值是否以某标记开头来选择行为,意味着任何共享该前缀的值也会选中它。除非该功能的语义本就是前缀,否则请匹配完整值。
机密或敏感 Exchange 状态的信息泄露
将密钥、内部 Exchange 状态、文件内容或配置值写入日志、事件、全局可读文件或 HTTP 响应的代码路径。
历史案例:CVE-2023-34442(camel-jira 将附件写入所有人可读的临时文件)、CVE-2024-22371(EventFactory 通过自定义事件暴露敏感的 Exchange 数据)、CVE-2026-49365(camel-netty-http)以及 CVE-2026-56139(camel-undertow)——muteException 消费者选项默认值为 false,因此处理错误会将完整的异常和堆栈跟踪返回给调用方。
这种模式并非 HTTP 独有。任何具有回复路径的消费者,都可能把路由的失败信息交还给消息的发送方——无论是作为响应体、通过套接字、封装在协议故障中,还是放在一个即使底层原因仍留在服务端、也会传输给调用方的状态字段里。概括地说:消费者绝不能把路由的异常返回给发送消息的一方。 能够回复的消费者需要一个默认值为 true 的 muteException 选项。服务契约中声明的故障属于例外,因为客户端就是依据这些故障编写的,屏蔽它们破坏的是契约,而非起到保护作用。
以默认的生产环境日志级别(INFO、WARN、ERROR)为评判标准:其影响仅在运维人员启用了诊断用的 DEBUG 或 TRACE 级别时才会显现的发现,不在考虑范围之内,因为这些级别是运维人员主动开启的诊断配置,本就预期会记录内部的 Exchange、路由和配置详情(参见 已知非问题 下的诊断日志条目)。
Exchange 之间共享的状态
在 Exchange 之外持有可变状态、并在多条消息之间重复使用该状态的组件,会让一条消息观察或修改另一条消息正在做的事情。发送前一条消息的一方未必就是发送下一条消息的一方,因此,只要一条路由服务于多个发送方、租户或合作伙伴,这就构成跨信任边界的行为。
这种状态有多种形式:数据格式反序列化后作为消息体返回的对象;在一次调用中累积输入、在另一次调用中消费输入的有状态加密原语;属于某个请求、却存放在下一个请求也能触及之处的密钥或凭据材料;跨进程共享的缓存。
两个问题决定其性质:
- 该状态是否不仅名义上、而且事实上是每个 Exchange 独立的? 任何能从生产者或消费者字段、静态变量、组件级缓存中访问到的状态,其存活时间都会超出写入它的那个 Exchange,在被证明并非如此之前,它就是共享的。「实际上它是单线程的」是某一次部署的属性,而不是代码的属性。
- 缓存键是否包含了所有会影响取值的因素? 当共享对象是某个端点被授权使用之物的缓存时,如果键遗漏了某个会改变缓存值所允许范围的字段,其缺陷与完全没有键是一样的。
这并不是“任何竞态条件都算漏洞”。只破坏失败交换自身结果的交错执行属于正确性缺陷。只有当共享状态承载了权限、身份或其他方的数据时,才在讨论范围之内。
不安全的默认配置
组件如果默认启用了与安全相关的选项——Java 反序列化、禁用 TLS 校验、监听 0.0.0.0 的管理端点、宽松的 HeaderFilterStrategy、未经过滤的 ObjectInputStream——无论其所属类别如何,均在讨论范围之内。问题在于:运维人员只是把这样一个组件添加到路由中而未做任何进一步配置,攻击者能拿它做什么。
历史案例:CVE-2020-11972、CVE-2020-11973、CVE-2026-40860 和 CVE-2026-43865 属于不安全默认配置的案例,同时也归入反序列化类别;CVE-2026-49365 和 CVE-2026-56139(muteException 默认为 false)则是信息泄露类别中的不安全默认配置案例。
有两种形态值得单独说明,因为在两者中,危险状态都是由“遗漏”造成的,而非主动选择启用——这正是它们与那些已明确记录、不在讨论范围内的“主动启用”选项之间的区别:
- 开启一项保护措施,绝不能以关闭另一项为代价。 启用传输安全时,如果对端验证材料未经配置,就必须回退到平台默认的信任锚,而绝不能变成接受所有对端。没有对端身份验证的加密连接,对路径上的攻击者而言几乎毫无意义;运维人员要求使用 TLS,并不等于要求跳过证书校验。只有在明确指定时,才应能启用“信任一切”。
- 启用 CORS 不得向任何未被指定的源授予凭据。 单纯回显请求来源本身是可以接受的;但既回显来源又允许携带凭据则不可接受,除非运维人员已将该来源列入白名单。两者结合便产生了“带凭据的任意源”策略,而 fetch 规范拒绝以字面量
*表达这种策略——这正是回显来源成为绕过该规则常用手段的原因。只要回显了来源,就始终要发送Vary: Origin,以免共享缓存把一个源的响应提供给另一个源。
对 Camel 构建的后端查询的注入
从接收到的输入构建其他语言查询的组件,绝不能将不可信输入直接拼接进该查询中。
历史案例:CVE-2025-66169 及其修复不彻底的后续 CVE-2026-46591(camel-neo4j 通过将 JSON 属性名插值到查询中而产生的 Cypher 注入)、CVE-2014-0003(camel-xslt 从不可信的样式表输入调用扩展函数)。
Camel 启动的外部进程中的参数注入
有些组件通过调用外部二进制程序来完成工作。在组件拼装命令行的地方,不受信任的输入只能作为数据(即参数向量中的一个值)传递给子进程,绝不能增加或修改某个参数。如果组件将不受信任的输入拼接进命令字符串,或者接受调用方提供的额外参数而不校验其是否属于已知的安全参数集合,就会让攻击者把一个数据字段变成二进制程序会执行的选项:例如输出路径标志、配置文件标志,或该工具暴露的任何其他选项。
历史案例:CVE-2026-40047(camel-docling),由于对传递给 docling 二进制程序的自定义 CLI 参数校验不足,同时导致了参数注入和路径遍历。
这一类问题与安全属性与违规严重程度中的第一条(“不受信任的数据绝不能被转化为要执行的代码或操作系统命令”)属于同一行列。它与路由作者的情形不同:路由作者编写带有攻击者可控命令的 exec 端点,按不在范围之内的规定不在讨论范围内;这里的这一类问题是框架代表路由作者构建参数向量。
不在范围之内
以下情况不属于框架漏洞。它们是有意为之的设计、运营方的责任,或是下游的误用。这些类别中的报告将被关闭,并标记为 not a vulnerability(非漏洞)。
- 路由作者编写的、可任意行事的代码。
.bean()、.process()、Runtime.exec()、simple/groovy/jexl/mvel求值、自定义处理器和 Bean 都属于路由代码,而路由代码是受信任的。如果路由作者把攻击者可控的头部当作simple表达式求值,责任在路由而非框架。只有当框架自身在路由作者并未要求的情况下把不可信输入交给求值器时,框架才在讨论范围之内。 - **路由作者用不可信输入拼接 SQL、Cypher、LDAP、XPath 或 HTTP URI 字符串而未做参数化。**各组件提供了安全的 API(参数绑定、预编译语句、URI 构建器),使用它们是路由作者的责任。
- 风险已写入文档、且必须显式设置才会启用该危险行为的选项。
allowJavaSerializedObject=true、transferException=true、trustAllCertificates=true、hostnameVerificationEnabled=false、显式选用使用ObjectInputStream的数据格式——这些都属于文档中明确的主动启用项,运维者已自行承担其后果。 - 仅在
dev或testprofile 下才会出现的行为。框架默认不应用任何 profile;dev、test和prod均需主动启用,通过camel.main.profile显式设置(或由 Camel CLI 等工具为你选择,本地开发时该工具会使用dev)。devprofile 仅用于开发,刻意放宽了防护——它会启用开发者控制台、调试与追踪端点、积压调试器以及更详细的诊断信息,并把insecure:dev策略放宽为allow。按设计,Camel 在这些模式下可能会暴露配置、路由和Exchange的细节,而这些在生产部署中不会暴露。如果某项报告的影响仅在camel.main.profile = dev或test时才显现,则属于仅限开发的配置,不在讨论范围之内。生产部署应运行camel.main.profile = prod,在该模式下安全策略会从默认的warn升级为fail;评判安全问题时所依据的正是这一生产形态(参见《*改变模型的配置变体》《部署加固》以及design/security.adoc设计文档,其中说明了随 profile 变化的策略默认值)。 - **通过资源耗尽造成的拒绝服务。**未限流的路由、无界的聚合器、没有速率限制的 HTTP 消费者、接受任意大小消息的 JMS 消费者——运维者必须施加
throttle、circuitBreaker、resilience4j、JVM 堆限制以及相关组件级选项。第三方库中的算法复杂度攻击应报告给上游项目,除非 Camel 暴露解析器的方式绕过了该库自身的限制。 - **部署者把
camel-management、开发者控制台、camel-jolokia、JMX 或其他管理面暴露在公共网络上。**这些属于管理面,它们假设网络是受信任的。它们提供的操作——包括ManagedCamelContext.sendBody/requestBody、ManagedBacklogDebugger.evaluateExpressionAtBreakpoint、addConditionalBreakpoint和BacklogTracer.setTraceFilter——在表达能力上刻意与路由作者的 DSL 相当,因为它们的存在就是为了支撑运维者的工作流(Camel CLI、Hawtio、JConsole、监控代理)。信任边界在于管理面本身——JVM JMX 认证(-Dcom.sun.management.jmxremote.authenticate)、Jolokia 限制器策略以及管理端口的网络暴露——而非单个 MBean 方法。一份报告若只是证明"从 JMX 或 JMelokia 连接调用 MBean 操作 X 会执行代码或向端点 Y 发送内容",描述的是文档中约定的行为,而非框架漏洞。 - **Camel TUI 的
--mcp与--web服务器。**Camel TUI(dsl/camel-jbang/camel-jbang-plugin-tui)可以选择性地暴露一个 MCP 服务器(--mcp,供 AI 智能体访问)和一个可通过浏览器访问的终端(--web,基于 WebSocket)。两者同属管理面,适用与上文相同的界定:需主动启用(不传该标志即关闭)、仅绑定到127.0.0.1,并且——与未配置认证层的 JMX 和 Jolokia 一样——除该回环地址绑定之外自身不带任何认证。从127.0.0.1可对 TUI 实施完全交互控制(包括它所能调起的一切外部程序,如docker/podman/camel run),这是这两个标志文档中约定的行为,而非框架漏洞。 - **第三方传递依赖中的漏洞。**Camel 修复的是 Camel 代码中的 CVE,而非第三方 JAR 中的;此类报告应提交给上游项目。Camel 可能会升级依赖以采纳上游修复,但 CVE 本身应向上游项目关闭。实际的 CVE 请参见
SECURITY.md及上游项目。 - **文档中明确以原型设计和开发为目的的功能。**有些便利功能的存在是为了让本地运行或演示变得简单,其契约在于覆盖面而非围栏式限制。
camel.server.staticEnabled通过先将请求解析到进程工作目录、再解析到 classpath 来提供静态内容,因此放在路由旁边的html/js文件或打包在 jar 中的文件会被直接提供:从 classpath 加载资源正是该选项的设计意图,而非疏漏。在不受信任的网络上运行此类功能属于部署决策,它在那里暴露的面由运维者负责。只有当某项功能的行为超出其自身声明的契约时——例如提供了运维者显式配置目录之外的路径——报告才在讨论范围之内。当某个组件或选项在文档中被描述为面向开发时,分诊时应以该文档作为契约。 - 由已认证用户对基于 Camel 构建的 UI 实施的自我型 XSS。
- 自动化扫描器提交的、未能证明具体信任边界被突破的报告。"组件 X 使用了历史上出现过 CVE 的类 Y"本身并不构成一个安全问题。报告必须证明该代码路径可从不可信来源到达,且信任边界确实被跨越。
已弃用和已移除的组件
组件在其生命周期中所处的位置,决定了针对它的报告将如何处理。组件是否已弃用是可以机械验证的:其 pom.xml 中的名称和文档标题带有 (deprecated) 后缀,带有 @Deprecated 注解,Camel 目录中标记有 deprecated 标志,并且升级指南中有相应条目指向替代方案或迁移方式。
- 已弃用的组件属于有限范围。 已弃用的组件正处于移除流程中,并且已有文档记录的替代方案或迁移方式。针对这类组件的报告仍会在私有安全列表中进行分类处理,但主要的修复手段是文档记录的迁移方式,而不一定是对已弃用组件的代码修改。根据严重程度以及该组件仍被广泛使用的程度,PMC 可能会直接修复、发布一条修复措施为"迁移到受支持的替代组件"的安全公告,或者加速移除。加固和纵深防御的工作会投入到受支持的替代组件上,而非已弃用的组件。
- 已移除的组件不在范围内。 不再随任何受支持版本发布的组件无法获得修复。安全问题必须针对存在于受支持版本中的组件进行验证;如果受影响的代码已被移除,那么解决办法就是升级到该代码已被移除或已被替换的版本。
- 对于未被弃用、仅仅依赖某个已弃用或已停止支持的第三方库的组件,此生命周期规则不会改变其范围内的类——这种情况适用上文范围之外部分中的第三方依赖条款。
已知限制
这些是框架的特性,乍看之下像是漏洞,但实际上是有文档记录的设计要点。它们可能会在今后被收紧;如果发生这种情况,相关变更会通过常规的升级指南渠道进行公告。
部分遗留组件默认采用宽松设置。 FTP、明文 SMTP、
mapJmsMessage=true等一直保持其原有行为不变,以确保兼容。当项目决定收紧某个默认值时,该变更会随升级指南条目一同发布;若旧默认值在默认安装的部署中构成安全风险,还会对应给出 CVE。通过内部头部进行基于 Bean 的分发是有意为之。
CamelBeanMethodName、CamelFileName、CamelExecCommandExecutable和CamelJmsDestinationName等头部是让路由控制组件行为的公开契约。路由作者必须从不受信任的生产者处过滤掉 Camel 内部头部(见下文部署加固);在组件一侧,自 4.21(CAMEL-23543)起,入站的Camel*HeaderFilterStrategy默认生效,组件作者不得选择退出。框架的自动头部过滤仅限于内部
Camel*命名空间。 自 4.21(CAMEL-23543)起,DefaultHeaderFilterStrategy默认以大小写不敏感的方式在双向、对每个使用它的消费者和生产者过滤该命名空间,无需进行任何按组件配置;它不会也无法过滤组件作为语义输入读取的无前缀应用级头部——camel-mail中的To、Cc、Bcc、Subject、From;HTTP 头部名称;JMS 属性;等等。这些头部是各组件文档化头部契约的一部分,会被有意透传。这里适用的是一条统一规则,而非按组件制定的策略:保护生产者的语义头部免受不受信任的上游影响是路由作者的职责——应在信任边界处剥离或规范化这些头部,正如处理由不受信任输入构造的查询字符串一样——而某个组件所认可的具体语义头部集合必然是因组件而异的,并在各组件页面上加以文档说明。在以下情形中,框架本身也属于责任范围:某个入站映射位置——消费者、数据格式、结构化内容模式或传输绑定——在其自身默认行为中将不受信任的输入映射到这些头部,却没有生效的入站HeaderFilterStrategy(与范围内的漏洞类别中 Camel 头部条目所指的同一类入站过滤机制,例如camel-mail中的 CVE-2026-33454);而当此类头部导航到配置根目录之外时,路径穿越类漏洞独立适用(例如 CVE-2018-8041)。
这一限制针对的是语义头部——即组件将其作为负载数据读取的那些头部。它不涉及组件自身的控制头部,后者用于选择目标、操作或传输方式及其凭据。无论这些头部如何拼写,它们都是组件的内部机制,属于该组件入站过滤集合的范畴,即使没有 Camel 前缀也是如此;针对此类头部的报告属于受理范围,而非路由编写者的责任。参见《受理范围内的漏洞类别》中 Camel 头部类别下的控制头部定义。
- 持久化 Java 对象的聚合仓库假定其底层存储是可信的。 JDBC、Cassandra、Infinispan、LevelDB、Consul 及类似的仓库是运维人员所编写的路由的状态存储;运维人员负责将该存储的写入访问限制在信任边界之内。这一假设针对的是路由自身写入并读回的状态。它不延伸到远程数据存储为其他主体放入其中的对象所报告的名称与元数据——blob 与对象键、远程文件名、列表条目——这些在《对手模型》下属于不可信输入,并已产生被受理的路径穿越类安全通告(CVE-2026-66906、CVE-2026-60093、CVE-2026-66907)。
- 许多组件继承其底层客户端的安全态势。
camel-jms继承 JMS 代理客户端的行为;camel-kafka继承 Kafka 客户端的行为;云 SDK 组件继承该 SDK 的 TLS 与认证默认设置。针对 Camel 的报告必须表明原因在于 Camel 框架本身,而非底层客户端。
已知的非问题项
自动化扫描器、AI 辅助分析工具与人工审阅者反复向 Camel 报告、但在本模型下不属于框架漏洞的模式。每一条均指明反复出现的说法、引用本文档中驳回该说法的章节,并在适当时给出抑制的形式。该列表是自动化分类流程中最具杠杆作用的输入;可将其原样反馈给扫描器,作为否定提示词或抑制配置。处置结果为 KNOWN-NON-FINDING(参见《分类处置》)。
「组件 X 依赖了含 CVE-Z 的 JAR,因此 Camel 存在漏洞。」 根据《超出范围》中关于传递依赖的条目,这属于超出范围。Camel 修复的是 Camel 代码中的 CVE,而不是第三方 JAR 中的;该报告应提交给上游。Camel 可能会升级该依赖以获得上游的修复,但该 CVE 本身应针对上游项目关闭。
「
simple(…)、xpath(…)、groovy(…)、jexl(…)或mvel(…)会求值不受信任的表达式。」 表达式文本是路由编写者的代码,而非不受信任的输入。只有当框架将Exchange的消息体、标头或属性传递给求值器,而路由编写者并未在此处放置表达式时,该框架才在范围内——即《核心路由引擎不变量》下的第一条不变量。否则,这属于《超出范围》中的路由编写者条目。「
.bean(…)、.process(…)、Runtime.exec(…)或Class引用可导致远程代码执行(RCE)。」 这些在设计上就是路由编写者的基础能力。路由代码属于可信代码;参见《超出范围》中的路由编写者条目以及《角色》中的路由编写者一行。「
Camel*标头控制分派,因此消费者存在漏洞。」 通过内部标头进行的 Bean 分派是让路由控制组件行为的公开契约;参见《已知限制》下的第二条说明。只有当入站映射点——即消费者、数据格式、结构化内容模式或传输绑定——在没有有效HeaderFilterStrategy的情况下,将来自不受信任来源的值提升到该命名空间中时,该发现才属于《范围内漏洞类别》中的 Camel 标头 / Bean 分派类。「应用级标头 X(
To、Subject、HTTPX-…、JMS 属性、AMQP / MQTT / CoAP / Kafka 标头)未被剥离,因此消费者存在漏洞。」 应用级标头是各组件文档化标头契约的一部分,会被有意透传;框架仅过滤内部的Camel*命名空间。参见《已知限制》下的第三条说明以及《未提供的安全属性》中的应用级标头一节。由路由编写者在信任边界处进行清理。
此条目仅适用于组件作为负载数据读取的标头。 在使用之前,请先检查标头 X 的实际作用:如果它用于选择目标、操作、传输方式及其凭据,那么它就是控制标头,无论其拼写方式如何都在适用范围内,其处置结果也不是 KNOWN-NON-FINDING —— 请参见《范围内漏洞类别》中 Camel-header 类下的控制标头定义,以及其中为 websocket.*、gridfs.*、irc.*、operationName 和 mail.smtp.* 所引用的安全公告。缺少 Camel 前缀本身并不能说明任何问题。
- "
DefaultHeaderFilterStrategy可以通过更改大小写(caMEL、CAMEL)绕过。" 默认策略开箱即用地不区分大小写(Camel、CAMEL和caMEL会被同样过滤);参见《已知限制》下的第三条要点。这里要构成一个发现,必须证明存在一个自定义策略,它没有继承DefaultHeaderFilterStrategy,并且重新实现的匹配逻辑不区分大小写 —— 而修复应当落在该自定义策略中。 - "开发者控制台、积压调试器、
Tracer/BacklogTracer、JMX、Jolokia 或camel-management暴露了可执行代码或读取Exchange状态的操作。" 这些属于管理面;信任边界是管理面本身(JVM 的 JMX 认证、Jolokia 限制器、管理端口的网络暴露),而非单个 MBean 方法。参见《不在范围内》中的管理面条目,以及《核心路由器引擎不变式》中的错误处理行。 - "某个发现仅在
camel.main.profile=dev或camel.main.profile=test下才会出现。" 属于非默认的仅开发用配置;按照《不在范围内》中的 profile 条目,不在适用范围内。 - "
camel-FOO在 DEBUG 或 TRACE 级别记录 Exchange 的正文、某个标头或配置值。" DEBUG 和 TRACE 是由运维人员显式启用的诊断日志级别;它们本就预期会暴露默认的 INFO、WARN 和 ERROR 级别不会显示的内部Exchange、路由与配置细节。信息泄露类发现依据默认的生产日志级别进行判定(参见《范围内漏洞类别》下的秘密或敏感 Exchange 状态的信息泄露类别,以及《未提供的安全属性》中的诊断日志级别要点)。本项目会在合理的情况下力求即使在诊断级别也不记录敏感数据,但并不承诺对这些数据进行脱敏处理。 - "
camel-FOO组件使用了 MD5 / SHA-1 / 非密码学哈希函数。" Camel 会出于非安全目的使用内容哈希,例如幂等键、基于内容的路由标识、分区选择器以及缓存键。要构成一个发现,该用途必须是安全原语(认证、完整性校验、密钥派生、签名),而不能是路由或标识用途。参见《未提供的安全属性》下的常数时间比较要点。 - "该组件声明了
HeaderFilterStrategy,因此其入站标头会被过滤。" 这属于反向的错误,它是不予关闭报告的理由,而非"非发现":一个先被构造然后被覆盖的策略,或者只在某个入口点被查询、而在同级入口点未被查询的策略,在真正重要的路径上什么也没有过滤(CVE-2026-78329、CAMEL-24419)。确认所声明的策略确实是活跃路径上被查询的那个实例,是对此类任何报告进行分级处理的一部分 —— 参见《范围内漏洞类别》中 Camel-header 类下的"从未被查询的过滤器不是过滤器"。 - "某个已弃用的组件仍然在发布,并且存在 CVE。" 已弃用的组件适用范围有限;主要的修复手段是按文档迁移到受支持的替代组件,而不一定是在该已弃用组件中进行修复。参见《已弃用和已移除的组件》。
- "
allowJavaSerializedObject=true、transferException=true、mapJmsMessage=true、trustAllCertificates=true或hostnameVerificationEnabled=false这类选项会启用不安全的行为。" 这些是文档中明确的可选项;运维人员已经显式接受了其后果。参见《不在范围内》中的显式可选项条目。 - "某个发现落在
core/camel-*模块中。" 首先按《核心路由器引擎不变式》进行路由。如果引擎维护了所列的每一项不变式,而违规仅是因为路由作者基于不可信输入编写了表达式或路由,或者在没有调用removeHeaders("Camel*")的情况下直接串联了不可信源,那么处置结果适用《不在范围内》中的路由作者立场。
分诊处置结论
漏洞报告、扫描器发现结果或 AI 辅助审查在依据本模型进行判定时,只能落入以下封闭的结果集合。每种处置结论都会引用授权它的章节,因此分诊响应是「参见本文档的 第 X 节」,而不是临时编写的说明。不符合下列任何处置结论的发现结果即为 MODEL-GAP,此时正确的做法是修订本模型(扩展范围内漏洞类别、范围之外、已知局限或不提供的安全属性),而不是临时关闭该报告。
| 分类 | 含义 | 对应依据 |
|---|---|---|
VALID | 违反了框架所声明的某项属性,且攻击者符合《攻击者模型》中定义的攻击者,输入被模型标记为不可信。通过协调发布进行修复,并以 CVE 公告形式发布。 | 安全属性与违规严重性、核心路由引擎不变量、在范围内漏洞类别、攻击者模型 |
VALID-HARDENING | 没有违反任何已声明的属性,但由于存在反复出现的误用方式或扫描器检测模式,框架决定在维护者裁量下加固默认行为或增加纵深防御检查。以私密方式报告;通常不带 CVE 一起发布;在升级指南中记录。若相邻组件的已受理发现会让此次修改看起来像一次静默修复,PMC 仍可能发布公告——CVE-2026-56140(camel-aws2-sns)记录了为一个仅生产者组件添加的入站过滤器,该组件不存在可达的注入路径,而 camel-aws2-sqs 的 CVE-2026-46456 中该路径是可达的。 | 已知限制、面向组件作者与审查者的指南 |
OUT-OF-MODEL: trusted-input | 需要控制被模型标记为可信的输入(路由 DSL、配置属性、由运维人员管控的文件)。 | 信任模型(角色、信任边界) |
OUT-OF-SCHEMA: adversary-not-in-scope | 需要攻击者模型所排除的某种攻击者能力(路由作者、部署运维人员、管理接口网络对端、传递性第三方依赖的作者)。 | 攻击者模型 |
OUT-OF-SCHEMA: unsupported-component | 受影响的组件已在受支持的版本中移除,或该发现针对的是框架交付范围之外的示例或样例代码。 | 已弃用与已移除的组件 |
OUT-OF-SCHEMA: non-default-build | 仅在非默认 profile(camel.main.profile = dev 或 test)、显式选择加入的选项(allowJavaSerializedObject=true、transferException=true、trustAllCertificates=true、hostnameVerificationEnabled=false、mapJmsMessage=true)或其他有文档说明的选择加入配置下才会出现。 | 不在范围内(profile 与显式选择加入的条目)、design/security.adoc |
BY-DESIGN: property-disclaimed | 涉及框架明确不提供的属性——拒绝服务/资源限制、JVM 沙箱、应用层请求头净化、传递性依赖的 CVE、常数时间比较、防止运维人员在框架默认值之外的错误配置。 | 不提供的安全属性、不在范围内 |
KNOWN-NON-FINDING | 符合已记录的反复出现的误报模式。 | 已知非发现项 |
MODEL-GAP | 不符合上述任何分类。此时应触发对本文档的修订(新增一个在范围内的类别、一个新的不在范围条目、一个新的已知限制或一个新的已声明不提供的属性),而不是对该报告做出临时裁断。 | 报告漏洞(PMC 审查)、升级指南条目 |
不完整的修复是一项新的发现,而不是旧案重开。 当某份已发布公告的补救措施事后被证明仍留有可触达的路径时,残留问题会依据本模型从头开始进行定级,若判定结果为 VALID,则会单独发布一份新公告,而不是对原公告进行修订。这种情况发生得足够频繁,已经构成一条常设规则,而无需逐案裁量;它通常呈现三种可辨识的形态:
- 修复只应用到了部分调用点,而非全部——CAMEL-24413 和 CAMEL-24420,为 CVE-2026-43865 而加入
camel-hazelcast的反序列化过滤器,并未应用到其余由 Camel 构建的配置上。 - 缓解措施虽然存在,但强度不足——CVE-2026-42527,默认的
ObjectInputFilter模式本身就放行了java.net.**。 - 缓解措施可被通向同一汇聚点的另一条路径绕过——CVE-2026-43866,伪造的
DefaultExchangeHolder绕过了为 CVE-2026-40860 添加的过滤器;以及 CVE-2026-46591,camel-neo4j中 CVE-2025-66169 的不完整修复后续问题。
这对报告者和定级工具的一个推论是:“这个漏洞已经在 CVE-X 中修复”并不构成一种处置结论。需要核实的主张是,新报告中的那条具体路径是否已被封堵,而不是该组件是否曾经打过补丁。
会改变本模型的配置变体
上文所述的安全姿态并非一个固定的单一设置;少量配置档(profile)选择、策略等级以及各组件的选项,会移动信任边界的所在位置,或改变框架对不安全配置的反应严格程度。本节汇总了会改变哪些性质得以成立的这些调节项,从而可以依据报告实际所需的配置来对其作出评判。本节只是将本文其他地方已陈述的事实集中到一处重述,并未引入任何新的承诺。
配置档(Profiles)
Camel 默认不应用任何配置档。配置档需通过 camel.main.profile 显式选择(或由工具选择——Camel CLI 在本地开发时会选择 dev)。配置档会设定默认的安全策略等级,并且在选择 dev 时,会开启一组开发功能。
camel.main.profile | 安全相关影响 | 分类处置结论 |
|---|---|---|
| 未设置(默认) | 安全策略框架默认为 warn:四类范畴中的不安全配置会在启动时记录日志,但不会阻止其生效。不会启用任何开发功能(开发者控制台、积压调试器、跟踪端点)。 | 基线态势。无论策略级别如何,不安全的选项始终需要显式启用(参见 逐选项显式启用)。 |
prod | 安全策略框架默认为 fail:四类范畴中的不安全配置会阻止启动。这是判定各项发现的参考态势。 | 如果某项发现仅因运维人员依赖未配置 profile 时的 warn 默认值而非 fail 才会出现,仍应根据该底层选项本身的情况进行分类,而该选项本身就是需要显式启用的。 |
dev | 仅限开发用途。启用开发者控制台、调试与跟踪端点、积压调试器及详细诊断,并将 insecure:dev 策略放宽为 allow。 | 仅在 dev 下出现的发现归类为 OUT-OF-MODEL: non-default-build。 |
test | 测试工具使用的测试 profile。不会放宽安全策略,也不会启用开发者控制台。 | 仅在 test 下出现的发现归类为 OUT-OF-MODEL: non-default-build。 |
安全策略级别
无论采用哪种 profile,这四个类别(secret、insecure:ssl、insecure:serialization、insecure:dev)中的每一个都可以通过 camel.security.policy 以及按类别覆盖的配置项(camel.security.secretPolicy、insecureSslPolicy、insecureSerializationPolicy、insecureDevPolicy)设置为 allow、warn(未使用 profile 时的默认值)或 fail。该策略框架是一个配置静态检查工具(configuration linter),用于在启动时检测不安全的配置(参见 Security properties not provided 一节中关于易混淆概念的说明);它不会拦截运行时数据。将某个类别放宽为 allow,或通过 camel.security.allowedProperties 豁免某个属性,属于运维人员的决策,本身并不会造成框架层面的安全漏洞。具体的设计约束请参见 design/security.adoc。
按选项逐项选择放宽
少量按组件配置的选项在设置为非默认值时,会放宽某项安全默认行为。这些选项的风险已在其文档中说明,选择启用它们属于运维人员的决策;若某项发现结果必须依赖这类选项,则标记为 OUT-OF-MODEL: non-default-build(或 BY-DESIGN: property-disclaimed),具体依据 Out of scope 一节中关于「显式选择启用(explicit-opt-in)」的条目。
| 选项 | 默认值 | 在不安全取值下的影响 |
|---|---|---|
allowJavaSerializedObject=true | false | HTTP(或类似)消费者接受并反序列化 application/x-java-serialized-object 请求体。 |
transferException=true | false | 序列化的异常对象会通过网络传输,从而在接收端形成反序列化攻击面。 |
mapJmsMessage=true | true(历史遗留) | JMS ObjectMessage 消息体会通过 getObject() 被实例化;在不可信的 broker 上,这会构成反序列化攻击面。该历史默认值由 ObjectInputFilter(CVE-2026-40860)和持有者伪造检查(CVE-2026-43866)加以防护。 |
trustAllCertificates=true | false | TLS 服务器证书校验被禁用。 |
hostnameVerificationEnabled=false | 取决于组件 | TLS 主机名校验被禁用。 |
这些变体、入口信任级别、在范围内与范围外的组件系列、已声明与未声明的属性、已知的非问题项以及分诊处置结果的机器可读索引,以附件形式 security-model.yaml 随本页一同发布;它是用于自动化分诊的派生索引,本文档页面仍为权威来源。
部署加固
以下事项由运维人员负责。若未执行,这些均不属于框架漏洞;但全部执行都能显著缩小攻击面。
在生产环境中显式选择
prod配置档(profile)。 框架默认不应用任何配置档;在没有配置档的情况下,安全策略框架对四个类别(secret、insecure:ssl、insecure:serialization、insecure:dev)默认使用warn策略——不安全的配置会被记录日志,但不会阻止启动。请设置camel.main.profile = prod,使策略升级为fail,从而让不安全的配置阻止启动。设置camel.main.profile = dev或test属于显式选择仅用于开发的特性(额外服务、开发控制台、调试端点),不应在生产环境中使用。当某个部署确实需要放宽策略时,请显式覆盖对应的单个类别。详情参见《会改变模型的配置变体》以及design/security.adoc设计文档。通过保险库(vault)解析机密。 使用受支持的后端之一(AWS Secrets Manager、Azure Key Vault、Google Secret Manager、HashiCorp Vault、IBM Secrets Manager、CyberArk Conjur),而不是在属性文件中使用明文值。
通过 JSSE 工具配置 TLS。 使用
SSLContextParameters显式设置信任库、密钥库、加密算法和协议。请勿在生产环境中使用trustAllCertificates=true或hostnameVerificationEnabled=false。在信任边界处剥离 Camel 内部头部。 当消费者从不可信的生产者接收消息时,请在消息进入任何分发处理器之前移除由 Camel 控制的头部:
- Java
- XML
- YAML
from("jetty:http://0.0.0.0:8080/api") .removeHeaders("Camel*") .to("direct:trusted-pipeline");<route> <from uri="jetty:http://0.0.0.0:8080/api"/> <removeHeaders pattern="Camel*"/> <to uri="direct:trusted-pipeline"/> </route>
- route:
from:
uri: jetty:http://0.0.0.0:8080/api
steps:
- removeHeaders:
pattern: "Camel*"
- to:
uri: direct:trusted-pipeline- 在较旧的版本上,还需剥离路由中各组件的控制头命名空间。 框架默认会过滤
Camel*命名空间,并已修复其发布的无前缀控制头(websocket.*、gridfs.*、irc.*、operationName、mail.smtp.*);每次修复都会在 /security/ 上的相应安全公告中注明受影响和已修复的版本。如果部署暂时还无法升级到包含这些修复的版本,请在信任边界处的removeHeaders模式中,于Camel*之外一并添加相关的前缀。 - 不要在暴露于不可信网络的消费者上启用 Java 序列化。 特别是,当上游消息代理不在信任边界内时,不要在 JMS 消费者上设置
allowJavaSerializedObject=true、transferException=true或mapJmsMessage=true。如果该选项无法避免,请安装ObjectInputFilter。 - 不要暴露管理接口。
camel-management、开发者控制台、camel-jolokia、JMX 以及 Camel TUI 的--mcp/--web服务器应当只监听回环接口、边车(sidecar)或独立网络。TUI 服务器默认已绑定127.0.0.1;不要在其前面架设反向代理使其可从公共网络访问。 - 及时修补组件。 将 Camel 固定在受支持的版本上,订阅 announce 邮件列表,并对 /security/ 上的安全公告及时响应。
- 以最小权限运行。 限制操作系统用户的文件系统、网络和进程权限;在容器部署中,丢弃不必要的 capabilities,仅挂载路由实际需要的文件系统路径。
- 使用最小依赖集。 只引入应用实际使用的 Camel 组件和第三方 JAR。每一个额外的依赖都会扩大攻击面和补丁维护责任。
面向组件作者与评审者的指导
在编写新组件或评审涉及现有组件的拉取请求时,以下问题决定了该变更是否符合安全模型。
该组件是否消费不受信任的输入? 自 4.21 起(CAMEL-23543),
DefaultHeaderFilterStrategy在默认情况下会拦截Camel*命名空间,且对每个使用它的消费者和生产者双向生效——匹配时不区分大小写(因此Camel、CAMEL和caMEL会被完全一致地过滤),也无需各组件编写任何样板代码。组件作者需要承担的其余职责是:不要退出(opt out)这一默认行为(正如ClassicJmsHeaderFilterStrategy为实现传统 JMS 透传而有意为之那样);在提供自定义策略时,继承DefaultHeaderFilterStrategy(或重新实现不区分大小写的Camel*匹配逻辑);并把组件自身的、不属于Camel*命名空间的内部头部,显式添加到过滤集合中。接下来的三项后续检查,用于判断你面前的这一改动是否真正做到了以上各点:
该组件的哪些头(header)属于控制头? 任何用于选择目标、操作或传输及其凭据的头,无论其拼写如何,都属于内部控制头,必须置于入站过滤集合中。新增头常量时应优先使用
Camel前缀,以便默认过滤器能够覆盖;对于必须保留的历史无前缀名称,则应显式过滤其命名空间。绝不能将控制头置于过滤器之外,指望路由作者自行将其剥离。该策略是否真正被使用? 构造出正确的策略还不够——要确认在使用之前,没有任何端点默认值、绑定构造器或 setter 将其替换掉,并且在所有代码路径上都能走到该策略,而不仅仅是测试所覆盖的那一条(CVE-2026-78329)。
每个入口点过滤的是否是同一命名空间? 消费者、数据格式的
unmarshal、各种结构化内容模式,以及任何查询参数或传输元数据的映射,填充的都是同一张头映射表。对其中一处加固时,必须在同一次修改中对其他几处一并加固(CVE-2026-59230 与 CAMEL-24419、CVE-2026-63621)。
该组件是否会反序列化为 Java 对象? 如果它在运维人员未显式控制的输入上调用了
ObjectInputStream.readObject()、XStream 风格的反序列化器,或支持多态的 Jackson 读取器,那么默认状态必须是安全的:要么安装了ObjectInputFilter,要么该特性仅限显式开启,要么组件拒绝反序列化未知类型。除了直接调用,还要留意间接调用路径:某个第三方 API 宣称支持“JDK 序列化”,实际上会代表你调用ObjectInputStream.readObject(),只搜索new ObjectInputStream(是发现不了的。若组件能让流经过CamelObjectInputStream,它就会继承 4.22 版新增的 JEP-290 默认过滤器(CAMEL-24296);但这只是底线,不能替代针对组件实际预期类型而限定作用域的过滤器。该组件是否会用一个并非由它自己选定的名称来构造本地路径、URL 或命令行? 远程对象与 Blob 名称、列表条目以及后端服务报告的文件名都属于不可信输入(参见威胁模型)。使用前要对结果进行规范化,并验证其解析后位于所配置的目录之内;在 Camel 表达式中,应优先使用
${file:onlyname}而非${file:name},后者会原样返回远程名称。将值传给外部二进制程序时,应把它们作为数据放入参数数组,并将调用方提供的任何额外参数与已知安全的参数集合进行校验。该组件是否会把 AI 模型的输出映射到
Exchange中? 模型输出——包括工具调用的字段名和参数——是不可信输入,而不是可信的控制通道。应通过任何其他入站映射点所使用的同一策略,将其过滤进头映射表,并将工具参数绑定到该工具实际声明的形参上(CVE-2026-49042)。某个
@UriParam是否控制着与安全相关的默认值? 应为其标注相应的security = "insecure:*"属性,使策略强制框架能够对其发出警告或直接报错。四种类别为secret、insecure:ssl、insecure:serialization、insecure:dev。参见design/security.adoc。该组件是否会持久化状态? 聚合仓库、幂等仓库及类似组件不得在没有
ObjectInputFilter的情况下调用ObjectInputStream.readObject();项目已因此模式连续接受了五则安全通告(CVE-2024-22369、CVE-2024-23114、CVE-2026-25747、CVE-2026-27172、CVE-2026-40858)。该组件是否提供身份认证或授权? 它必须落实其选项名称所声称的功能——校验令牌的签发者、受众和签名;覆盖对应处理器所声明的每一个子路径;默认拒绝(fail closed)。有两个具体的陷阱,各自都牵涉不止一则通告:其一,配置缺失的检查必须默认拒绝或拒绝启动,绝不能悄悄退出校验链(CVE-2026-66908、CVE-2026-53913、CAMEL-24411);其二,在组件对路径、主机或标识符做规范化处理的地方,授权决策必须基于与分发(dispatch)决策完全相同的规范化后的值来计算(CVE-2026-40022、CAMEL-24412)。拒绝路径还必须真正终止交换(exchange),而不能仅仅设置一个响应,否则后续步骤可能将其覆盖。
该组件是否在交换之间保留状态? 生产者或消费者上的任何字段、任何静态成员、任何组件级缓存,其存活时间都会超过写入它的那次交换。要追问:后续的发送方是否可能读取或干扰它?需要优先排查的情况包括:共享的反序列化目标对象、有状态的密码学对象,以及存储在请求之外的请求级密钥材料。当共享对象是一个缓存时,缓存键必须包含所有会影响缓存值所允许操作的字段。
该组件是否会把凭据发送到路由未选定的地方? 凭据只应归属于端点配置所指定的授权方(authority)。如果组件跟随重定向,目标由远程服务器选定,因此一旦授权方发生变化,就绝不能重新附加凭据,也不能将其注册到通配符主机作用域下。对于由对端而非运维人员提供的任何地址同样如此:回调 URL、回执目的地、重新登录端点。
该组件是否会把响应写回给发来消息的一方? 如果它可能返回路由失败,就需要一个默认值为
true的muteException选项。相关规则及已声明故障的例外情况,参见上文的信息泄露一节。本次修改是否放宽了默认值? 对于这四类
security类别,新的默认值应倾向于“除非显式开启,否则一律拒绝”。如果必须放宽某个默认值,此次修改需要配套新增一条升级指南条目,并经 PMC 评审。
报告漏洞
Apache Camel 项目采用标准的 ASF 漏洞报告流程:
- 阅读 Apache Camel 安全 页面。
- 向 private-security@camel.apache.org 发送邮件,说明漏洞描述、受影响的版本,以及能够证明信任边界被突破的概念验证(PoC)。
- 对于尚未发布的漏洞,请勿提交公开的 Jira 工单、开启公开的拉取请求,或在邮件列表、社交媒体及任何其他公开渠道发布相关信息——在协调修复方案发布之前,避免泄露任何与该潜在问题相关的内容。仅联系 Apache 软件基金会安全团队 报告问题,并遵循其指示。
符合上述范围内类别的报告将在私有安全邮件列表中进行分诊,在协调发布中修复,并作为 CVE 公告发布。符合范围外类别的报告将被关闭,并附上指向本文档的参考链接。
- 安全 - 面向用户的安全目录(路由、负载、端点、配置安全、保险库)。
- Camel 配置工具 - 用于 SSL/TLS 配置的 JSSE 工具。
design/security.adoc(源码树中) - 安全策略强制框架的设计文档。- Apache Camel 安全 - 公开的公告索引与报告流程。
SECURITY.md(源码树中) - GitHub 上渲染的安全指引文件。security-model.yaml(本页面的附件) - 本模型的机器可读索引(入口点信任、范围内/外的类别族、配置变体、已声明与已否认的属性、已知的非发现项、分诊处置结论),供自动化分诊工具使用。本文字页面为权威版本。
评论
登录后参与评论
KnowForge