docs/release_notes/v1.17.5.md
This update contains a critical security fix:
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.
Any deployment using access control policies for service invocation is affected. An attacker who can reach the Dapr API (HTTP or gRPC) could:
admin%2F..%2Fpublic) to reach an allowed path (/public) while the method started from a denied prefix (/admin).%23) or query (%3F) characters to cause the ACL to evaluate a different path than what was delivered to the target application.% 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.
The method path was normalized independently in two places:
purell.NormalizeURLString which treated the method as a URL — decoding %XX, resolving ../, and stripping # as a fragment delimiter and ? as a query delimiter.constructRequest for 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.
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.