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
No known key found for this signature in database
GPG Key ID: 5F311AB48A55D521
32 changed files with 123 additions and 655 deletions

View File

@ -64,7 +64,7 @@ import org.springframework.util.Assert;
* X-Content-Type-Options: nosniff
* Strict-Transport-Security: max-age=31536000 ; includeSubDomains
* X-Frame-Options: DENY
* X-XSS-Protection: 1; mode=block
* X-XSS-Protection: 0
* </pre>
*
* @author Rob Winch
@ -73,6 +73,7 @@ import org.springframework.util.Assert;
* @author Eddú Meléndez
* @author Vedran Pavic
* @author Ankur Pathak
* @author Daniel Garnier-Moiroux
* @since 3.2
*/
public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
@ -733,50 +734,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
enable();
}
/**
* If false, will not specify the mode as blocked. In this instance, any content
* will be attempted to be fixed. If true, the content will be replaced with "#".
* @param enabled the new value
* @deprecated use
* {@link XXssConfig#headerValue(XXssProtectionHeaderWriter.HeaderValue)} instead
*/
@Deprecated
public XXssConfig block(boolean enabled) {
this.writer.setBlock(enabled);
return this;
}
/**
* If true, the header value will contain a value of 1. For example:
*
* <pre>
* X-XSS-Protection: 1
* </pre>
*
* or if {@link XXssProtectionHeaderWriter#setBlock(boolean)} of the given
* {@link XXssProtectionHeaderWriter} is true
*
*
* <pre>
* X-XSS-Protection: 1; mode=block
* </pre>
*
* If false, will explicitly disable specify that X-XSS-Protection is disabled.
* For example:
*
* <pre>
* X-XSS-Protection: 0
* </pre>
* @param enabled the new value
* @deprecated use
* {@link XXssConfig#headerValue(XXssProtectionHeaderWriter.HeaderValue)} instead
*/
@Deprecated
public XXssConfig xssProtectionEnabled(boolean enabled) {
this.writer.setEnabled(enabled);
return this;
}
/**
* Sets the value of the X-XSS-PROTECTION header. OWASP recommends using
* {@link XXssProtectionHeaderWriter.HeaderValue#DISABLED}.

View File

@ -69,10 +69,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_DISABLED = "disabled";
private static final String ATT_ENABLED = "enabled";
private static final String ATT_BLOCK = "block";
private static final String ATT_POLICY = "policy";
private static final String ATT_STRATEGY = "strategy";
@ -583,20 +579,6 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XXssProtectionHeaderWriter.class);
if (xssElt != null) {
boolean disabled = "true".equals(getAttribute(xssElt, ATT_DISABLED, "false"));
String enabled = xssElt.getAttribute(ATT_ENABLED);
if (StringUtils.hasText(enabled)) {
if (disabled) {
attrNotAllowed(parserContext, ATT_ENABLED, ATT_DISABLED, xssElt);
}
builder.addPropertyValue("enabled", enabled);
}
String block = xssElt.getAttribute(ATT_BLOCK);
if (StringUtils.hasText(block)) {
if (disabled) {
attrNotAllowed(parserContext, ATT_BLOCK, ATT_DISABLED, xssElt);
}
builder.addPropertyValue("block", block);
}
XXssProtectionHeaderWriter.HeaderValue headerValue = XXssProtectionHeaderWriter.HeaderValue
.from(xssElt.getAttribute(ATT_HEADER_VALUE));
if (headerValue != null) {

View File

@ -1040,7 +1040,7 @@ public class ServerHttpSecurity {
* X-Content-Type-Options: nosniff
* Strict-Transport-Security: max-age=31536000 ; includeSubDomains
* X-Frame-Options: DENY
* X-XSS-Protection: 1; mode=block
* X-XSS-Protection: 0
* </pre>
*
* such that "Strict-Transport-Security" is only added on secure requests.
@ -1081,7 +1081,7 @@ public class ServerHttpSecurity {
* X-Content-Type-Options: nosniff
* Strict-Transport-Security: max-age=31536000 ; includeSubDomains
* X-Frame-Options: DENY
* X-XSS-Protection: 1; mode=block
* X-XSS-Protection: 0
* </pre>
*
* such that "Strict-Transport-Security" is only added on secure requests.

View File

@ -25,18 +25,12 @@ import org.springframework.security.web.header.writers.XXssProtectionHeaderWrite
* idiomatic Kotlin code.
*
* @author Eleftheria Stein
* @author Daniel Garnier-Moiroux
* @since 5.3
* @property block whether to specify the mode as blocked
* @property xssProtectionEnabled if true, the header value will contain a value of 1.
* If false, will explicitly disable specify that X-XSS-Protection is disabled.
* @property headerValue the value of the X-XSS-Protection header. OWASP recommends [HeaderValue.DISABLED].
*/
@HeadersSecurityMarker
class XssProtectionConfigDsl {
@Deprecated("use headerValue instead")
var block: Boolean? = null
@Deprecated("use headerValue instead")
var xssProtectionEnabled: Boolean? = null
var headerValue: HeaderValue? = null
private var disabled = false
@ -50,8 +44,6 @@ class XssProtectionConfigDsl {
internal fun get(): (HeadersConfigurer<HttpSecurity>.XXssConfig) -> Unit {
return { xssProtection ->
block?.also { xssProtection.block(block!!) }
xssProtectionEnabled?.also { xssProtection.xssProtectionEnabled(xssProtectionEnabled!!) }
headerValue?.also { xssProtection.headerValue(headerValue) }
if (disabled) {

View File

@ -1268,13 +1268,7 @@ xss-protection.attlist &=
## disable the X-XSS-Protection header. Default is 'false' meaning it is enabled.
attribute disabled {xsd:boolean}?
xss-protection.attlist &=
## specify that XSS Protection should be explicitly enabled or disabled. Default is 'true' meaning it is enabled.
attribute enabled {xsd:boolean}?
xss-protection.attlist &=
## Add mode=block to the header or not, default is on.
attribute block {xsd:boolean}?
xss-protection.attlist &=
## Specify the value for the X-Xss-Protection header. When set, overrides both enabled and block attributes.
## Specify the value for the X-Xss-Protection header. Defaults to "0".
attribute header-value {"0"|"1"|"1; mode=block"}?
content-type-options =

View File

@ -3553,23 +3553,9 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="enabled" type="xs:boolean">
<xs:annotation>
<xs:documentation>specify that XSS Protection should be explicitly enabled or disabled. Default is 'true'
meaning it is enabled.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="block" type="xs:boolean">
<xs:annotation>
<xs:documentation>Add mode=block to the header or not, default is on.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="header-value">
<xs:annotation>
<xs:documentation>Specify the value for the X-Xss-Protection header. When set, overrides both enabled and
block attributes.
<xs:documentation>Specify the value for the X-Xss-Protection header. Defaults to "0".
</xs:documentation>
</xs:annotation>
<xs:simpleType>

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

View File

@ -62,7 +62,7 @@ class HeadersDslTests {
header { string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate") }
header { string(HttpHeaders.EXPIRES, "0") }
header { string(HttpHeaders.PRAGMA, "no-cache") }
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1; mode=block") }
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0") }
}
}

View File

@ -106,7 +106,7 @@ class HttpSecurityDslTests {
string(HttpHeaders.PRAGMA, "no-cache")
}
header {
string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1; mode=block")
string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0")
}
}
}

View File

@ -36,6 +36,7 @@ import org.springframework.test.web.servlet.get
* Tests for [XssProtectionConfigDsl]
*
* @author Eleftheria Stein
* @author Daniel Garnier-Moiroux
*/
@ExtendWith(SpringTestContextExtension::class)
class XssProtectionConfigDslTests {
@ -52,7 +53,7 @@ class XssProtectionConfigDslTests {
this.mockMvc.get("/") {
secure = true
}.andExpect {
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1; mode=block") }
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0") }
}
}
@ -71,62 +72,6 @@ class XssProtectionConfigDslTests {
}
}
@Test
fun `headers when XSS protection with block false then mode is not block in header`() {
this.spring.register(XssProtectionBlockFalseConfig::class.java).autowire()
this.mockMvc.get("/") {
secure = true
}.andExpect {
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1") }
}
}
@Configuration
@EnableWebSecurity
open class XssProtectionBlockFalseConfig {
@Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
defaultsDisabled = true
xssProtection {
block = false
}
}
}
return http.build()
}
}
@Test
fun `headers when XSS protection disabled then X-XSS-Protection header is 0`() {
this.spring.register(XssProtectionDisabledConfig::class.java).autowire()
this.mockMvc.get("/") {
secure = true
}.andExpect {
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0") }
}
}
@Configuration
@EnableWebSecurity
open class XssProtectionDisabledConfig {
@Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
defaultsDisabled = true
xssProtection {
xssProtectionEnabled = false
}
}
}
return http.build()
}
}
@Test
fun `headers when XSS protection disabled then X-XSS-Protection header not in response`() {
this.spring.register(XssProtectionDisabledFunctionConfig::class.java).autowire()
@ -155,26 +100,54 @@ class XssProtectionConfigDslTests {
}
@Test
fun `headers when XSS protection header value disabled then X-XSS-Protection header is 0`() {
this.spring.register(XssProtectionHeaderValueDisabledFunctionConfig::class.java).autowire()
fun `headers when XSS protection header value enabled then X-XSS-Protection header is 1`() {
this.spring.register(XssProtectionHeaderValueEnabledFunctionConfig::class.java).autowire()
this.mockMvc.get("/") {
secure = true
}.andExpect {
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0") }
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1") }
}
}
@Configuration
@EnableWebSecurity
open class XssProtectionHeaderValueDisabledFunctionConfig () {
open class XssProtectionHeaderValueEnabledFunctionConfig {
@Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
defaultsDisabled = true
xssProtection {
headerValue = XXssProtectionHeaderWriter.HeaderValue.DISABLED
headerValue = XXssProtectionHeaderWriter.HeaderValue.ENABLED
}
}
}
return http.build()
}
}
@Test
fun `headers when XSS protection header value enabled_mode_block then X-XSS-Protection header is 1 and mode=block`() {
this.spring.register(XssProtectionHeaderValueEnabledModeBlockFunctionConfig::class.java).autowire()
this.mockMvc.get("/") {
secure = true
}.andExpect {
header { string(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1; mode=block") }
}
}
@Configuration
@EnableWebSecurity
open class XssProtectionHeaderValueEnabledModeBlockFunctionConfig {
@Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
defaultsDisabled = true
xssProtection {
headerValue = XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK
}
}
}

View File

@ -71,7 +71,7 @@ class ServerHeadersDslTests {
.expectHeader().valueEquals(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")
.expectHeader().valueEquals(HttpHeaders.EXPIRES, "0")
.expectHeader().valueEquals(HttpHeaders.PRAGMA, "no-cache")
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block")
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0")
}
@Configuration

View File

@ -126,7 +126,7 @@ class ServerHttpSecurityDslTests {
.expectHeader().valueEquals(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")
.expectHeader().valueEquals(HttpHeaders.EXPIRES, "0")
.expectHeader().valueEquals(HttpHeaders.PRAGMA, "no-cache")
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block")
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0")
}
@Configuration

View File

@ -57,7 +57,7 @@ class ServerXssProtectionDslTests {
this.client.get()
.uri("/")
.exchange()
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1 ; mode=block")
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0")
}
@Configuration
@ -107,7 +107,7 @@ class ServerXssProtectionDslTests {
this.client.get()
.uri("/")
.exchange()
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "0")
.expectHeader().valueEquals(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION, "1")
}
@EnableWebFluxSecurity
@ -118,7 +118,7 @@ class ServerXssProtectionDslTests {
return http {
headers {
xssProtection {
headerValue = XXssProtectionServerHttpHeadersWriter.HeaderValue.DISABLED
headerValue = XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED
}
}
}

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2018 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<headers defaults-disabled="true">
<xss-protection enabled="false"/>
</headers>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2018 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<headers defaults-disabled="true">
<xss-protection enabled="false" block="true"/>
</headers>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2022 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<headers defaults-disabled="true">
<xss-protection enabled="false" header-value="1"/>
</headers>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2018 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<headers defaults-disabled="true">
<xss-protection enabled="true"/>
</headers>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2018 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<headers>
<xss-protection disabled="true" enabled="true"/>
</headers>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2002-2018 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<headers>
<xss-protection disabled="true" block="true"/>
</headers>
<intercept-url pattern="/**" access="permitAll"/>
</http>
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
<b:import resource="userservice.xml"/>
</b:beans>

View File

@ -33,7 +33,7 @@ Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 0
----
====
@ -209,18 +209,14 @@ See the relevant sections to see how to customize the defaults for both xref:ser
====
Some browsers have built-in support for filtering out https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OWASP-DV-001)[reflected XSS attacks].
This is by no means foolproof but does assist in XSS protection.
The filter has been deprecated in major browsers, and https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html#x-xss-protection[current OWASP recommendation] is to explicitly set the header to 0.
The filtering is typically enabled by default, so adding the header typically just ensures it is enabled and instructs the browser what to do when a XSS attack is detected.
For example, the filter might try to change the content in the least invasive way to still render everything.
At times, this type of replacement can become an https://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/[XSS vulnerability in itself].
Instead, it is best to block the content rather than attempt to fix it.
By default, Spring Security blocks the content by using the following header:
====
[source]
----
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 0
----
====

View File

@ -255,8 +255,8 @@ fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
[[webflux-headers-xss-protection]]
== X-XSS-Protection
By default, Spring Security instructs browsers to block reflected XSS attacks by using the <<headers-xss-protection,X-XSS-Protection header>.
You can disable `X-XSS-Protection`:
By default, Spring Security instructs browsers to disable the XSS Auditor by using <<headers-xss-protection,X-XSS-Protection header>.
You can disable the `X-XSS-Protection` header entirely:
.X-XSS-Protection Customization
====
@ -291,6 +291,41 @@ fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
----
====
You can also change the header value:
.X-XSS-Protection Explicit header value
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.xssProtection(xssProtection -> xssProtection.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK))
);
return http.build();
}
----
.Kotlin
[source,kotlin,role="secondary"]
----
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
xssProtection {
headerValue = XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK
}
}
}
}
----
====
[[webflux-headers-csp]]
== Content Security Policy (CSP)
By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-csp[Content Security Policy], because a reasonable default is impossible to know without the context of the application.

View File

@ -571,23 +571,10 @@ This is in no-way a full protection to XSS attacks!
Do not include the header for https://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / Type-1 Cross-Site Scripting (XSS)] protection.
[[nsa-xss-protection-enabled]]
* **xss-protection-enabled**
Explicitly enable or disable https://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / Type-1 Cross-Site Scripting (XSS)] protection.
[[nsa-xss-protection-block]]
* **xss-protection-block**
When true and xss-protection-enabled is true, adds mode=block to the header.
This indicates to the browser that the page should not be loaded at all.
When false and xss-protection-enabled is true, the page will still be rendered when an reflected attack is detected but the response will be modified to protect against the attack.
Note that there are sometimes ways of bypassing this mode which can often times make blocking the page more desirable.
[[nsa-xss-protection-header-value]]
* **xss-protection-header-value**
Explicitly set the value for https://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / Type-1 Cross-Site Scripting (XSS)] header.
One of: "0", "1", "1; mode=block".
When set, overrides both enabled and block attributes.
One of: "0", "1", "1; mode=block". Defaults to "0".
[[nsa-xss-protection-parents]]

View File

@ -529,9 +529,10 @@ class SecurityConfig {
[[servlet-headers-xss-protection]]
== X-XSS-Protection
By default, Spring Security instructs browsers to block reflected XSS attacks by using the <<headers-xss-protection,X-XSS-Protection header>.
By default, Spring Security instructs browsers to disable the XSS Auditor by using <<headers-xss-protection,X-XSS-Protection header>.
However, you can change this default.
For example, the following configuration specifies that Spring Security should no longer instruct browsers to block the content:
For example, the following configuration specifies that Spring Security instruct compatible browsers to enable filtering,
and block the content:
.X-XSS-Protection Customization
====
@ -548,7 +549,7 @@ public class WebSecurityConfig {
// ...
.headers(headers -> headers
.xssProtection(xss -> xss
.block(false)
.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)
)
);
return http.build();
@ -563,7 +564,7 @@ public class WebSecurityConfig {
<!-- ... -->
<headers>
<xss-protection block="false"/>
<xss-protection headerValue="1; mode=block"/>
</headers>
</http>
----
@ -581,7 +582,7 @@ class SecurityConfig {
http {
headers {
xssProtection {
block = false
headerValue = XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK
}
}
}

View File

@ -29,6 +29,7 @@ import org.springframework.util.Assert;
*
* @author Rob Winch
* @author Ankur Pathak
* @author Daniel Garnier-Moiroux
* @since 3.2
*/
public final class XXssProtectionHeaderWriter implements HeaderWriter {
@ -41,7 +42,7 @@ public final class XXssProtectionHeaderWriter implements HeaderWriter {
* Create a new instance
*/
public XXssProtectionHeaderWriter() {
this.headerValue = HeaderValue.ENABLED_MODE_BLOCK;
this.headerValue = HeaderValue.DISABLED;
}
@Override
@ -51,55 +52,6 @@ public final class XXssProtectionHeaderWriter implements HeaderWriter {
}
}
/**
* If true, will contain a value of 1. For example:
*
* <pre>
* X-XSS-Protection: 1
* </pre>
*
* or if {@link #setBlock(boolean)} is true
*
*
* <pre>
* X-XSS-Protection: 1; mode=block
* </pre>
*
* If false, will explicitly disable specify that X-XSS-Protection is disabled. For
* example:
*
* <pre>
* X-XSS-Protection: 0
* </pre>
* @param enabled the new value
* @deprecated use {@link XXssProtectionHeaderWriter#setHeaderValue(HeaderValue)}
* instead
*/
@Deprecated
public void setEnabled(boolean enabled) {
if (!enabled) {
this.headerValue = HeaderValue.DISABLED;
}
else if (this.headerValue == HeaderValue.DISABLED) {
this.headerValue = HeaderValue.ENABLED;
}
}
/**
* If false, will not specify the mode as blocked. In this instance, any content will
* be attempted to be fixed. If true, the content will be replaced with "#".
* @param block the new value
* @deprecated use {@link XXssProtectionHeaderWriter#setHeaderValue(HeaderValue)}
* instead
*/
@Deprecated
public void setBlock(boolean block) {
if (this.headerValue == HeaderValue.DISABLED && block) {
throw new IllegalArgumentException("Cannot set block to true with enabled false");
}
this.headerValue = block ? HeaderValue.ENABLED_MODE_BLOCK : HeaderValue.ENABLED;
}
/**
* Sets the value of the X-XSS-PROTECTION header.
* <p>

View File

@ -41,7 +41,7 @@ public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersW
* Creates a new instance
*/
public XXssProtectionServerHttpHeadersWriter() {
this.headerValue = HeaderValue.ENABLED_MODE_BLOCK;
this.headerValue = HeaderValue.DISABLED;
updateDelegate();
}
@ -51,57 +51,8 @@ public class XXssProtectionServerHttpHeadersWriter implements ServerHttpHeadersW
}
/**
* If true, will contain a value of 1. For example:
*
* <pre>
* X-XSS-Protection: 1
* </pre>
*
* or if {@link #setBlock(boolean)} is true
*
*
* <pre>
* X-XSS-Protection: 1; mode=block
* </pre>
*
* If false, will explicitly disable specify that X-XSS-Protection is disabled. For
* example:
*
* <pre>
* X-XSS-Protection: 0
* </pre>
* @param enabled the new value
* @deprecated use
* {@link XXssProtectionServerHttpHeadersWriter#setHeaderValue(HeaderValue)} instead
*/
@Deprecated
public void setEnabled(boolean enabled) {
if (!enabled) {
this.headerValue = HeaderValue.DISABLED;
}
else if (this.headerValue == HeaderValue.DISABLED) {
this.headerValue = HeaderValue.ENABLED;
}
updateDelegate();
}
/**
* If false, will not specify the mode as blocked. In this instance, any content will
* be attempted to be fixed. If true, the content will be replaced with "#".
* @param block the new value
* @deprecated use
* {@link XXssProtectionServerHttpHeadersWriter#setHeaderValue(HeaderValue)} instead
*/
@Deprecated
public void setBlock(boolean block) {
Assert.isTrue(this.headerValue != HeaderValue.DISABLED || !block,
"Cannot set block to true with enabled false");
this.headerValue = block ? HeaderValue.ENABLED_MODE_BLOCK : HeaderValue.ENABLED;
updateDelegate();
}
/**
* Sets the value of the X-XSS-PROTECTION header.
* Sets the value of the X-XSS-PROTECTION header. Defaults to
* {@link HeaderValue#DISABLED}
* <p>
* If {@link HeaderValue#DISABLED}, will specify that X-XSS-Protection is disabled.
* For example:

View File

@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
/**
* @author Rob Winch
* @author Ankur Pathak
* @author Daniel Garnier-Moiroux
*
*/
public class XXssProtectionHeaderWriterTests {
@ -49,43 +50,11 @@ public class XXssProtectionHeaderWriterTests {
@Test
public void writeHeaders() {
this.writer.writeHeaders(this.request, this.response);
assertThat(this.response.getHeaderNames()).hasSize(1);
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("1; mode=block");
}
@Test
public void writeHeadersNoBlock() {
this.writer.setBlock(false);
this.writer.writeHeaders(this.request, this.response);
assertThat(this.response.getHeaderNames()).hasSize(1);
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("1");
}
@Test
public void writeHeadersDisabled() {
this.writer.setBlock(false);
this.writer.setEnabled(false);
this.writer.writeHeaders(this.request, this.response);
assertThat(this.response.getHeaderNames()).hasSize(1);
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("0");
}
@Test
public void setEnabledFalseWithBlockTrue() {
this.writer.setEnabled(false);
this.writer.writeHeaders(this.request, this.response);
assertThat(this.response.getHeaderNames()).hasSize(1);
assertThat(this.response.getHeaderValues("X-XSS-Protection")).containsOnly("0");
}
@Test
public void setBlockTrueWithEnabledFalse() {
this.writer.setBlock(false);
this.writer.setEnabled(false);
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setBlock(true));
}
@Test
public void writeHeaderWhenNotPresent() {
String value = new String("value");

View File

@ -46,23 +46,6 @@ public class XXssProtectionServerHttpHeadersWriterTests {
@Test
public void writeHeadersWhenNoHeadersThenWriteHeaders() {
this.writer.writeHttpHeaders(this.exchange);
assertThat(this.headers).hasSize(1);
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION))
.containsOnly("1 ; mode=block");
}
@Test
public void writeHeadersWhenBlockFalseThenWriteHeaders() {
this.writer.setBlock(false);
this.writer.writeHttpHeaders(this.exchange);
assertThat(this.headers).hasSize(1);
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION)).containsOnly("1");
}
@Test
public void writeHeadersWhenEnabledFalseThenWriteHeaders() {
this.writer.setEnabled(false);
this.writer.writeHttpHeaders(this.exchange);
assertThat(this.headers).hasSize(1);
assertThat(this.headers.get(XXssProtectionServerHttpHeadersWriter.X_XSS_PROTECTION)).containsOnly("0");