From d1776989edde65fc42450057e0942c175f2f990b Mon Sep 17 00:00:00 2001 From: Andrey Litvitski Date: Wed, 23 Jul 2025 22:31:51 +0300 Subject: [PATCH] Add Referrer-Policy header to default security headers Closes: gh-13567 Signed-off-by: Andrey Litvitski --- .../web/configurers/HeadersConfigurer.java | 24 +++++++++++++++++++ .../HttpSecurityConfigurationTests.java | 4 +++- .../configurers/HeadersConfigurerTests.java | 8 +++++-- .../NamespaceHttpHeadersTests.java | 1 + 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java index 10986daef59..d4cc3178d43 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java @@ -66,6 +66,7 @@ * Strict-Transport-Security: max-age=31536000 ; includeSubDomains * X-Frame-Options: DENY * X-XSS-Protection: 0 + * Referrer-Policy: no-referrer * * * @author Rob Winch @@ -75,6 +76,7 @@ * @author Vedran Pavic * @author Ankur Pathak * @author Daniel Garnier-Moiroux + * @author Andrey Litvitski * @since 3.2 */ public class HeadersConfigurer> @@ -266,6 +268,7 @@ public HeadersConfigurer defaultsDisabled() { this.cacheControl.disable(); this.hsts.disable(); this.frameOptions.disable(); + this.referrerPolicy.disable(); return this; } @@ -968,6 +971,27 @@ public final class ReferrerPolicyConfig { private ReferrerPolicyHeaderWriter writer; private ReferrerPolicyConfig() { + enable(); + } + + /** + * Disables Referrer Policy + * @return the {@link HeadersConfigurer} for additional configuration + */ + public HeadersConfigurer disable() { + this.writer = null; + return HeadersConfigurer.this; + } + + /** + * Ensures the Referrer Policy header is enabled if it is not already. + * @return the {@link ReferrerPolicyConfig} for additional customization + */ + public ReferrerPolicyConfig enable() { + if (this.writer == null) { + this.writer = new ReferrerPolicyHeaderWriter(); + } + return this; } /** diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java index 955ad614ae7..c9abad19868 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java @@ -141,11 +141,13 @@ public void getWhenDefaultFilterChainBeanThenDefaultHeadersInResponse() throws E .andExpect(header().string(HttpHeaders.EXPIRES, "0")) .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")) + .andExpect(header().string(HttpHeaders.REFERRER_POLICY, "no-referrer")) .andReturn(); // @formatter:on assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder( HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY, - HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION); + HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION, + HttpHeaders.REFERRER_POLICY); } @Test diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java index 779754b524c..3ba90bf51ba 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java @@ -81,10 +81,12 @@ public void getWhenHeadersConfiguredThenDefaultHeadersInResponse() throws Except .andExpect(header().string(HttpHeaders.EXPIRES, "0")) .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")) + .andExpect(header().string(HttpHeaders.REFERRER_POLICY, "no-referrer")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder( HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY, - HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION); + HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION, + HttpHeaders.REFERRER_POLICY); } @Test @@ -98,10 +100,12 @@ public void getWhenHeadersConfiguredInLambdaThenDefaultHeadersInResponse() throw .andExpect(header().string(HttpHeaders.EXPIRES, "0")) .andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")) .andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")) + .andExpect(header().string(HttpHeaders.REFERRER_POLICY, "no-referrer")) .andReturn(); assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder( HttpHeaders.X_CONTENT_TYPE_OPTIONS, HttpHeaders.X_FRAME_OPTIONS, HttpHeaders.STRICT_TRANSPORT_SECURITY, - HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION); + HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION, + HttpHeaders.REFERRER_POLICY); } @Test diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java index 4a59f2312e0..10fd56eea17 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java @@ -65,6 +65,7 @@ public class NamespaceHttpHeadersTests { defaultHeaders.put("Expires", "0"); defaultHeaders.put("Pragma", "no-cache"); defaultHeaders.put("X-XSS-Protection", "0"); + defaultHeaders.put("Referrer-Policy", "no-referrer"); } public final SpringTestContext spring = new SpringTestContext(this);