Security best practices in Knative serving

Knative serving relies on Istio for ingress. Therefore, you are able to customize and configure Istio to support your needs. This also means that Knative serving can be affected by known issues or vulnerabilities in Istio.

This page was created to help ensure that you configure Knative serving using known best practices, and that you address any known issues to avoid unintentionally exposing your resources to vulnerabilities.

Other best practices guides and resources:

Known vulnerabilities

Configuring paths in AuthorizationPolicies

Security vulnerability:

Description:

You can use Istio's AuthorizationPolicies for access control using the paths to your Knative serving services. Due to CVE-2021-31920, if you configure path-based access control you might be vulnerable to path confusion attacks.

For example, given a service at yourservice.com/admin, for which you configured access to allow requests to the path /admin. If you do not explicitly deny access to //admin, the path vulnerability in AuthorizationPolicy fails to prevent access for requests that use the malformed //admin path. Because your service might not differentiate between those paths, the request to a malformed path is allowed unintended access.

Background:

The default Istio ingress gateway that is used by Knative serving relies on default URL pattern normalization, using the normalize_path option on Envoy proxies, which follows RFC 3986.

Unfortunately, there are several known request URL patterns that are not normalized through the default URL pattern normalization standards. See the following section about how you can mitigate the vulnerability.

Mitigation:

To help ensure that you are not vulnerable to path confusion attacks today, there are two possible methods that you can implement:

  • Recommended option: Deny all access by default

    Configure Istio to use a default-deny pattern for AuthorizationPolicy policies. Generally, this improves your cluster's security posture. Configuring a default-deny authorization pattern denies all requests to your services by default and allows you to explicitly define all the conditions for which a request is allowed access.

    Using this pattern might mean that if you fail to allow a specific condition, certain requests will be unexpectedly denied. This might result in poor user experience, service outage, or failure to meet your SLO or SLA. The tradeoff for explicitly defining all access is usually preferred over a security incident due to unintended access.

    Example:

    Create a AuthorizationPolicy to use the default-deny pattern by defining a allow-nothing policy in your target namespace. For example, to denys all traffic to all services in the default namespace, you create:

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: allow-nothing
      namespace: default
    spec:
      {}
    

    To learn more about defining a AuthorizationPolicy type policy, see Istio authorization for HTTP traffic.

  • Alternative option: Explicitly deny all problematic URL variations to your service

    To avoid implementing a default-deny pattern, you must ensure that your backend service is able to deny any problematic paths. Depending on your language, framework, and other factors in how you implement your service, you must explicitly deny all URL paths that the Istio ingress gateway does not normalize, including:

    • Multiple forward slashes or backslashes: //, \\
    • Escaped sequences of forward slashes or backslashes: %2F, %2f, %5C, %5c