1
0
mirror of synced 2026-05-22 21:33:16 +00:00

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
@@ -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}.
@@ -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) {
@@ -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.
@@ -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) {
@@ -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 =
@@ -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>
@@ -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(
@@ -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
@@ -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
@@ -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();
}
@@ -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(
@@ -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
@@ -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") }
}
}
@@ -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")
}
}
}
@@ -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
}
}
}
@@ -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
@@ -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
@@ -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
}
}
}
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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>