spring-cloud-gateway icon indicating copy to clipboard operation
spring-cloud-gateway copied to clipboard

SecureHeaders filter at route level is not working for downloadOptions and permissionPolicy with 2025.0.0

Open SinhaAmit opened this issue 5 months ago • 0 comments

Describe the bug

Issue 1: SecureHeaders filter at route level is not working for downloadOptions and permissionPolicy

Works with springCloudVersion: 2024.0.2

spring:
  cloud:
    gateway:
      routes:
        - id: api-testing
          uri: http://localhost:8081
          order: 1
          predicates:
            - Path=/gateway/api/json/**
          filters:
            - RewritePath=/gateway/(?<segment>.*), /$\{segment}
            - name: SecureHeaders
              args:
                xssProtectionHeader: route_level
                strictTransportSecurity: route_level
                contentTypeOptions: route_level
                frameOptions: route_level
                referrerPolicy: route_level
                contentSecurityPolicy: route_level
                downloadOptions: route_level
                permittedCrossDomainPolicies: route_level
$ curl http://localhost:8080/gateway/api/json/realm -v
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
* using HTTP/1.x
> GET /gateway/api/json/realm HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.14.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: application/json
< Matched-Stub-Id: 7f4f6c07-265a-4a95-bf89-82ea01bd919f
< Vary: Accept-Encoding, User-Agent
< X-Xss-Protection: route_level
< Strict-Transport-Security: route_level
< X-Frame-Options: route_level
< X-Content-Type-Options: route_level
< Referrer-Policy: route_level
< Content-Security-Policy: route_level
< X-Download-Options: route_level
< X-Permitted-Cross-Domain-Policies: route_level

Not Working with springCloudVersion: 2025.0.0

The above route configuration doesn't work, so I migrated it as follows:

spring:
  cloud:
    gateway:
      server:
        webflux:
          routes:
            - id: api-testing
              uri: http://localhost:8081
              order: 1
              predicates:
                - Path=/gateway/api/json/**
              filters:
                - RewritePath=/gateway/(?<segment>.*), /$\{segment}
                - name: SecureHeaders
                  args:
                    xssProtectionHeaderValue: route_level
                    strictTransportSecurityHeaderValue: route_level
                    frameOptionsHeaderValue: route_level
                    contentTypeOptionsHeaderValue: route_level
                    referrerPolicyHeaderValue: route_level
                    contentSecurityPolicyHeaderValue: route_level
                    downloadOptionsHeaderValue: route_level
                    permittedCrossDomainPoliciesHeaderValue: route_level
                    permissionPolicyHeaderValue: route_level
$ curl http://localhost:8080/gateway/api/json/realm -v
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
* using HTTP/1.x
> GET /gateway/api/json/realm HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.14.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: application/json
< Matched-Stub-Id: 7f4f6c07-265a-4a95-bf89-82ea01bd919f
< Vary: Accept-Encoding, User-Agent
< X-Xss-Protection: route_level
< Strict-Transport-Security: route_level
< X-Frame-Options: route_level
< X-Content-Type-Options: route_level
< Referrer-Policy: route_level
< Content-Security-Policy: route_level
< X-Download-Options: noopen
< X-Permitted-Cross-Domain-Policies: route_level

As observed, the X-Download-Options header is using the default value instead of the one configured at the route level. Additionally, the Permissions-Policy header is missing from the response.

Issue 2: The differing property names between SecureHeadersGatewayFilterFactory.Config and SecureHeadersProperties make the configuration somewhat confusing

SecureHeadersProperties:

	private String xssProtectionHeader = X_XSS_PROTECTION_HEADER_DEFAULT;
	private String strictTransportSecurity = STRICT_TRANSPORT_SECURITY_HEADER_DEFAULT;
	private String frameOptions = X_FRAME_OPTIONS_HEADER_DEFAULT;
	private String contentTypeOptions = X_CONTENT_TYPE_OPTIONS_HEADER_DEFAULT;
	private String referrerPolicy = REFERRER_POLICY_HEADER_DEFAULT;
	private String contentSecurityPolicy = CONTENT_SECURITY_POLICY_HEADER_DEFAULT;
	private String downloadOptions = X_DOWNLOAD_OPTIONS_HEADER_DEFAULT;
	private String permittedCrossDomainPolicies = X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER_DEFAULT;
	private String permissionsPolicy = PERMISSIONS_POLICY_HEADER_OPT_IN_DEFAULT;

SecureHeadersGatewayFilterFactory.Config:

	private String routePermissionsPolicyHeaderValue;
	private String xssProtectionHeaderValue;
	private String strictTransportSecurityHeaderValue;
	private String frameOptionsHeaderValue;
	private String contentTypeOptionsHeaderValue;
	private String referrerPolicyHeaderValue;
	private String contentSecurityPolicyHeaderValue;
	private String downloadOptionsHeaderValue;
	private String permittedCrossDomainPoliciesHeaderValue;
	private String permissionPolicyHeaderValue;

Also, it's strange we have two properties for permissionPolicy, routePermissionsPolicyHeaderValue and permissionPolicyHeaderValue, neither of which work.

SinhaAmit avatar Aug 04 '25 05:08 SinhaAmit