spring-cloud / spring-cloud/spring-cloud-gateway

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

Open
#3,874 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading SecureHeadersGatewayFilterFactory.Config and SecureHeadersProperties, then reproduce the route-level configuration shown for springCloudVersion 2025.0.0. Trace how downloadOptions and permissionPolicy are bound and emitted; done means both configured headers appear with the route values and the related property names behave consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.