dapr v1.16.14 版本更新介绍
发布日期: 2026-04-16
版本号: v1.16.14
Dapr 1.16.14版本包含一项关键安全修复,解决了服务调用路径遍历绕过访问控制策略的问题。该漏洞允许攻击者通过编码的URL保留字符和路径遍历序列(如
admin%2F..%2Fpublic)来绕过ACL策略,从而访问原本被拒绝的目标路径。影响范围包括所有使用服务调用访问控制策略的部署,攻击者可通过HTTP或gRPC API利用此漏洞。 问题根源在于ACL和调度层对方法路径的独立处理不一致:ACL使用purell进行规范化解码,而调度层使用原始字符串,导致ACL授权的路径与实际送达目标应用的路径不同。 修复方案是在服务调用边缘(HTTP和gRPC API入口、内部调用及代理处理)统一进行路径规范化处理,使用path.Clean解析路径并移除purell依赖,确保ACL检查与出站调度使用相同的规范化路径。作为纵深防御,HTTP通道的constructRequest也会对方法路径进行path.Clean处理。强烈建议用户升级到此版本。
更新内容 (中文)
Dapr 1.16.14
此更新包含一项关键安全修复:
安全:服务调用路径遍历绕过访问控制策略
问题描述
服务调用方法路径中的保留URL字符和路径遍历序列可能绕过访问控制策略。 拥有访问Dapr HTTP或gRPC API权限的攻击者,可以调用本应被访问控制列表(ACL)策略拒绝的目标应用程序操作。
影响范围
所有使用访问控制策略进行服务调用的部署均受影响。能够访问Dapr API(HTTP或gRPC)的攻击者可以:
- 使用编码的路径遍历(
admin%2F..%2Fpublic)访问允许路径(/public),而该方法起始于被拒绝的前缀(/admin)。 - 使用编码片段(
%23)或查询(%3F)字符,使ACL评估的路径与传递给目标应用程序的路径不同。 - 使用裸露的
%符号导致ACL规范化崩溃,可能完全绕过策略。
gRPC API是更危险的攻击向量,因为gRPC将方法作为原始字符串传递,没有客户端URL清洗——#、?、%、../和控制字符都被原样传递。
根本原因
方法路径在两个地方独立进行了规范化:
- ACL使用
purell.NormalizeURLString,将方法视为URL处理——解码%XX、解析../,并将#作为片段分隔符、?作为查询分隔符去除。 - 调度层(HTTP使用
constructRequest,gRPC直接传递)使用原始方法字符串。
这造成了不匹配:ACL授权的路径与目标应用程序接收的路径不同。例如,admin%2F..%2Fpublic被ACL规范化为public(允许),但目标应用程序接收到的是原始的admin/../public。
解决方案
方法路径现在在服务调用边缘进行规范化:对于HTTP和gRPC公共API调用在directMessaging.Invoke中,对于gRPC内部调用在callLocalValidateACL中,对于代理调用在gRPC代理处理器中。规范化形式同时用于ACL检查和出站调度,消除了不匹配。ACL成为纯粹的策略评估层,自身不再执行规范化。
对于HTTP,Go的net/http服务器在提取方法之前对r.URL.Path进行百分比编码解码。对于gRPC,方法字符串是原始的(无百分比解码),被视为不透明值——百分比编码序列如%2F是字面字符,而非路径分隔符。
规范化使用path.Clean解析../和重复斜杠,并拒绝包含#、?、空字节或控制字符的方法路径。ACL路径中已移除purell依赖。
作为纵深防御措施,HTTP通道中的constructRequest在构建出站URL之前对方法应用了path.Clean。
强烈建议用户升级到此版本。
更新内容 (原始)
Dapr 1.16.14
This update contains a critical security fix:
Security: Service invocation path traversal bypasses access control policies
Problem
Reserved URL characters and path traversal sequences in service invocation method paths could bypass access control policies. An attacker with access to the Dapr HTTP or gRPC API could invoke operations on a target application that the ACL was configured to deny.
Impact
Any deployment using access control policies for service invocation is affected. An attacker who can reach the Dapr API (HTTP or gRPC) could:
- Use encoded path traversal (
admin%2F..%2Fpublic) to reach an allowed path (/public) while the method started from a denied prefix (/admin). - Use encoded fragment (
%23) or query (%3F) characters to cause the ACL to evaluate a different path than what was delivered to the target application. - Use a bare
%to crash the ACL normalization, potentially bypassing the policy entirely.
The gRPC API was the more dangerous vector because gRPC passes the method as a raw string with no client-side URL sanitization — #, ?, %, ../, and control characters were all delivered literally.
Root Cause
The method path was normalized independently in two places:
- The ACL used
purell.NormalizeURLStringwhich treated the method as a URL — decoding%XX, resolving../, and stripping#as a fragment delimiter and?as a query delimiter. - The dispatch layer (
constructRequestfor HTTP, gRPC passthrough) used the raw method string.
This created a mismatch: the ACL authorized one path while the target application received a different one. For example, admin%2F..%2Fpublic was normalized by the ACL to public (allowed), but the target application received the raw admin/../public.
Solution
The method path is now normalized at the service invocation edge — in directMessaging.Invoke for HTTP and gRPC public API calls, in callLocalValidateACL for gRPC internal calls, and in the gRPC proxy handler for proxied calls. The normalized form is used for both the ACL check and the outbound dispatch, eliminating the mismatch. The ACL is a pure policy evaluation layer and performs no normalization of its own.
For HTTP, Go’s net/http server decodes percent-encoding in r.URL.Path before the method is extracted. For gRPC, method strings are raw (no percent-decoding) and are treated as opaque — percent-encoded sequences like %2F are literal characters, not path separators.
Normalization uses path.Clean to resolve ../ and duplicate slashes, and rejects method paths containing #, ?, null bytes, or control characters. The purell dependency has been removed from the ACL path.
As defense-in-depth, constructRequest in the HTTP channel applies path.Clean to the method before building the outbound URL.
Users are strongly encouraged to upgrade to this release.
下载链接
- daprd_darwin_amd64.tar.gz
- daprd_darwin_amd64.tar.gz.sha256
- daprd_darwin_arm64.tar.gz
- daprd_darwin_arm64.tar.gz.sha256
- daprd_linux_amd64-stablecomponents.tar.gz
- daprd_linux_amd64-stablecomponents.tar.gz.sha256
- daprd_linux_amd64.tar.gz
- daprd_linux_amd64.tar.gz.sha256
- daprd_linux_arm-stablecomponents.tar.gz
- daprd_linux_arm-stablecomponents.tar.gz.sha256
- daprd_linux_arm.tar.gz
- daprd_linux_arm.tar.gz.sha256
- daprd_linux_arm64-stablecomponents.tar.gz
- daprd_linux_arm64-stablecomponents.tar.gz.sha256
- daprd_linux_arm64.tar.gz
- daprd_linux_arm64.tar.gz.sha256
- daprd_windows_amd64.zip
- daprd_windows_amd64.zip.sha256
- grafana-actor-dashboard.json
- grafana-actor-dashboard.json.sha256
- grafana-sidecar-dashboard.json
- grafana-sidecar-dashboard.json.sha256
- grafana-system-services-dashboard.json
- grafana-system-services-dashboard.json.sha256
- injector_darwin_amd64.tar.gz
- injector_darwin_amd64.tar.gz.sha256
- injector_darwin_arm64.tar.gz
- injector_darwin_arm64.tar.gz.sha256
- injector_linux_amd64.tar.gz
- injector_linux_amd64.tar.gz.sha256
- injector_linux_arm.tar.gz
- injector_linux_arm.tar.gz.sha256
- injector_linux_arm64.tar.gz
- injector_linux_arm64.tar.gz.sha256
- injector_windows_amd64.zip
- injector_windows_amd64.zip.sha256
- operator_darwin_amd64.tar.gz
- operator_darwin_amd64.tar.gz.sha256
- operator_darwin_arm64.tar.gz
- operator_darwin_arm64.tar.gz.sha256
- operator_linux_amd64.tar.gz
- operator_linux_amd64.tar.gz.sha256
- operator_linux_arm.tar.gz
- operator_linux_arm.tar.gz.sha256
- operator_linux_arm64.tar.gz
- operator_linux_arm64.tar.gz.sha256
- operator_windows_amd64.zip
- operator_windows_amd64.zip.sha256
- placement_darwin_amd64.tar.gz
- placement_darwin_amd64.tar.gz.sha256
- placement_darwin_arm64.tar.gz
- placement_darwin_arm64.tar.gz.sha256
- placement_linux_amd64.tar.gz
- placement_linux_amd64.tar.gz.sha256
- placement_linux_arm.tar.gz
- placement_linux_arm.tar.gz.sha256
- placement_linux_arm64.tar.gz
- placement_linux_arm64.tar.gz.sha256
- placement_windows_amd64.zip
- placement_windows_amd64.zip.sha256
- scheduler_darwin_amd64.tar.gz
- scheduler_darwin_amd64.tar.gz.sha256
- scheduler_darwin_arm64.tar.gz
- scheduler_darwin_arm64.tar.gz.sha256
- scheduler_linux_amd64.tar.gz
- scheduler_linux_amd64.tar.gz.sha256
- scheduler_linux_arm.tar.gz
- scheduler_linux_arm.tar.gz.sha256
- scheduler_linux_arm64.tar.gz
- scheduler_linux_arm64.tar.gz.sha256
- scheduler_windows_amd64.zip
- scheduler_windows_amd64.zip.sha256
- sentry_darwin_amd64.tar.gz
- sentry_darwin_amd64.tar.gz.sha256
- sentry_darwin_arm64.tar.gz
- sentry_darwin_arm64.tar.gz.sha256
- sentry_linux_amd64.tar.gz
- sentry_linux_amd64.tar.gz.sha256
- sentry_linux_arm.tar.gz
- sentry_linux_arm.tar.gz.sha256
- sentry_linux_arm64.tar.gz
- sentry_linux_arm64.tar.gz.sha256
- sentry_windows_amd64.zip
- sentry_windows_amd64.zip.sha256