Default X-Xss-Protection header value to "0"

Closes gh-9631
This commit is contained in:
Daniel Garnier-Moiroux
2022-10-06 12:00:31 +02:00
committed by Steve Riesenberg
parent dcda899c8c
commit 27059ced87
32 changed files with 123 additions and 655 deletions

View File

@@ -122,7 +122,7 @@ public class HttpSecurityConfigurationTests {
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block"))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0"))
.andReturn();
// @formatter:on
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(

View File

@@ -57,7 +57,7 @@ public class HeadersConfigurerEagerHeadersTests {
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
.andExpect(header().string("X-XSS-Protection", "1; mode=block"));
.andExpect(header().string("X-XSS-Protection", "0"));
}
@Configuration

View File

@@ -80,7 +80,7 @@ public class HeadersConfigurerTests {
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).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);
@@ -97,7 +97,7 @@ public class HeadersConfigurerTests {
.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache"))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).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);
@@ -169,16 +169,16 @@ public class HeadersConfigurerTests {
throws Exception {
this.spring.register(XssProtectionConfig.class).autowire();
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).andReturn();
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
}
@Test
public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredValueDisabledThenOnlyXssProtectionHeaderInResponse()
public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredEnabledModeBlockThenOnlyXssProtectionHeaderInResponse()
throws Exception {
this.spring.register(XssProtectionValueDisabledConfig.class).autowire();
this.spring.register(XssProtectionValueEnabledModeBlockConfig.class).autowire();
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).andReturn();
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
}
@@ -186,16 +186,16 @@ public class HeadersConfigurerTests {
public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception {
this.spring.register(XssProtectionInLambdaConfig.class).autowire();
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).andReturn();
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
}
@Test
public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredValueDisabledInLambdaThenOnlyXssProtectionHeaderInResponse()
public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredValueEnabledModeBlockInLambdaThenOnlyXssProtectionHeaderInResponse()
throws Exception {
this.spring.register(XssProtectionValueDisabledInLambdaConfig.class).autowire();
this.spring.register(XssProtectionValueEnabledModeBlockInLambdaConfig.class).autowire();
MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "0")).andReturn();
.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
}
@@ -719,7 +719,7 @@ public class HeadersConfigurerTests {
@Configuration
@EnableWebSecurity
static class XssProtectionValueDisabledConfig {
static class XssProtectionValueEnabledModeBlockConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
@@ -728,7 +728,7 @@ public class HeadersConfigurerTests {
.headers()
.defaultsDisabled()
.xssProtection()
.headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED);
.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK);
// @formatter:on
return http.build();
}
@@ -755,7 +755,7 @@ public class HeadersConfigurerTests {
@Configuration
@EnableWebSecurity
static class XssProtectionValueDisabledInLambdaConfig {
static class XssProtectionValueEnabledModeBlockInLambdaConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
@@ -765,7 +765,7 @@ public class HeadersConfigurerTests {
headers
.defaultsDisabled()
.xssProtection((xXssConfig) ->
xXssConfig.headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED)
xXssConfig.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)
)
);
// @formatter:on

View File

@@ -62,7 +62,7 @@ public class NamespaceHttpHeadersTests {
defaultHeaders.put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
defaultHeaders.put("Expires", "0");
defaultHeaders.put("Pragma", "no-cache");
defaultHeaders.put("X-XSS-Protection", "1; mode=block");
defaultHeaders.put("X-XSS-Protection", "0");
}
public final SpringTestContext spring = new SpringTestContext(this);
@@ -116,7 +116,7 @@ public class NamespaceHttpHeadersTests {
@Test
public void requestWhenXssCustomThenBehaviorMatchesNamespace() throws Exception {
this.spring.register(XssProtectionCustomConfig.class).autowire();
this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1")));
this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1; mode=block")));
}
@Test
@@ -291,7 +291,7 @@ public class NamespaceHttpHeadersTests {
// xss-protection@enabled and xss-protection@block
.defaultsDisabled()
.xssProtection()
.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED);
.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK);
// @formatter:on
return http.build();
}

View File

@@ -62,7 +62,7 @@ public class HttpHeadersConfigTests {
.put("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
.put("Expires", "0")
.put("Pragma", "no-cache")
.put("X-XSS-Protection", "1; mode=block")
.put("X-XSS-Protection", "0")
.build();
// @formatter:on
@@ -351,32 +351,6 @@ public class HttpHeadersConfigTests {
excludedHeaders.remove("X-XSS-Protection");
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtection")).autowire();
// @formatter:off
this.mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(header().string("X-XSS-Protection", "1; mode=block"))
.andExpect(excludes(excludedHeaders));
// @formatter:on
}
@Test
public void requestWhenEnablingXssProtectionThenDefaultsToModeBlock() throws Exception {
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
excludedHeaders.remove("X-XSS-Protection");
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionEnabled")).autowire();
// @formatter:off
this.mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(header().string("X-XSS-Protection", "1; mode=block"))
.andExpect(excludes(excludedHeaders));
// @formatter:on
}
@Test
public void requestWhenDisablingXssProtectionThenDefaultsToZero() throws Exception {
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
excludedHeaders.remove("X-XSS-Protection");
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabled")).autowire();
// @formatter:off
this.mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(header().string("X-XSS-Protection", "0"))
@@ -423,33 +397,6 @@ public class HttpHeadersConfigTests {
// @formatter:on
}
@Test
public void requestWhenSettingXssProtectionDisabledHeaderValueToOneThenDefaultsToOne() throws Exception {
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
excludedHeaders.remove("X-XSS-Protection");
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabledAndHeaderValueOne")).autowire();
// @formatter:off
this.mvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(header().string("X-XSS-Protection", "1"))
.andExpect(excludes(excludedHeaders));
// @formatter:on
}
@Test
public void configureWhenXssProtectionDisabledAndBlockSetThenAutowireFails() {
/*
* NOTE: Original error message "Cannot set block to true with enabled false" no
* longer shows up in stack trace as of Spring Framework 6.x.
*
* See https://github.com/spring-projects/spring-framework/issues/25162.
*/
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> this.spring
.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabledAndBlockSet")).autowire())
.havingRootCause().withMessageContaining("Property 'block' threw exception");
}
@Test
public void requestWhenUsingCacheControlThenRespondsWithCorrespondingHeaders() throws Exception {
Map<String, String> includedHeaders = ImmutableMap.<String, String>builder()
@@ -693,21 +640,6 @@ public class HttpHeadersConfigTests {
.withMessageContaining("request-matcher-ref");
}
@Test
public void configureWhenXssProtectionDisabledAndEnabledThenAutowireFails() {
assertThatExceptionOfType(BeanDefinitionParsingException.class)
.isThrownBy(() -> this.spring.configLocations(this.xml("XssProtectionDisabledAndEnabled")).autowire())
.withMessageContaining("enabled");
}
@Test
public void configureWhenXssProtectionDisabledAndBlockSpecifiedThenAutowireFails() {
assertThatExceptionOfType(BeanDefinitionParsingException.class)
.isThrownBy(
() -> this.spring.configLocations(this.xml("XssProtectionDisabledSpecifyingBlock")).autowire())
.withMessageContaining("block");
}
@Test
public void configureWhenXssProtectionDisabledAndHeaderValueSpecifiedThenAutowireFails() {
assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(

View File

@@ -75,7 +75,7 @@ public class HeaderSpecTests {
this.expectedHeaders.add(HttpHeaders.EXPIRES, "0");
this.expectedHeaders.add(ContentTypeOptionsServerHttpHeadersWriter.X_CONTENT_OPTIONS, "nosniff");
this.expectedHeaders.add(XFrameOptionsServerHttpHeadersWriter.X_FRAME_OPTIONS, "DENY");
this.expectedHeaders.add(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block");
this.expectedHeaders.add(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0");
}
@Test