Add X-Xss-Protection headerValue to XML config
Issue gh-9631
This commit is contained in:
parent
039e0328e1
commit
0e215a21ad
|
@ -101,6 +101,8 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
private static final String ATT_POLICY_DIRECTIVES = "policy-directives";
|
private static final String ATT_POLICY_DIRECTIVES = "policy-directives";
|
||||||
|
|
||||||
|
private static final String ATT_HEADER_VALUE = "header-value";
|
||||||
|
|
||||||
private static final String CACHE_CONTROL_ELEMENT = "cache-control";
|
private static final String CACHE_CONTROL_ELEMENT = "cache-control";
|
||||||
|
|
||||||
private static final String HPKP_ELEMENT = "hpkp";
|
private static final String HPKP_ELEMENT = "hpkp";
|
||||||
|
@ -595,6 +597,14 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
}
|
}
|
||||||
builder.addPropertyValue("block", block);
|
builder.addPropertyValue("block", block);
|
||||||
}
|
}
|
||||||
|
XXssProtectionHeaderWriter.HeaderValue headerValue = XXssProtectionHeaderWriter.HeaderValue
|
||||||
|
.from(xssElt.getAttribute(ATT_HEADER_VALUE));
|
||||||
|
if (headerValue != null) {
|
||||||
|
if (disabled) {
|
||||||
|
attrNotAllowed(parserContext, ATT_HEADER_VALUE, ATT_DISABLED, xssElt);
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("headerValue", headerValue);
|
||||||
|
}
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1299,6 +1299,9 @@ xss-protection.attlist &=
|
||||||
xss-protection.attlist &=
|
xss-protection.attlist &=
|
||||||
## Add mode=block to the header or not, default is on.
|
## Add mode=block to the header or not, default is on.
|
||||||
attribute block {xsd:boolean}?
|
attribute block {xsd:boolean}?
|
||||||
|
xss-protection.attlist &=
|
||||||
|
## Specify the value for the X-Xss-Protection header. When set, overrides both enabled and block attributes.
|
||||||
|
attribute header-value {"0"|"1"|"1; mode=block"}?
|
||||||
|
|
||||||
content-type-options =
|
content-type-options =
|
||||||
## Add a X-Content-Type-Options header to the resopnse. Value is always 'nosniff'.
|
## Add a X-Content-Type-Options header to the resopnse. Value is always 'nosniff'.
|
||||||
|
|
|
@ -3652,6 +3652,20 @@
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
</xs:attribute>
|
</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>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="0"/>
|
||||||
|
<xs:enumeration value="1"/>
|
||||||
|
<xs:enumeration value="1; mode=block"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
</xs:attributeGroup>
|
</xs:attributeGroup>
|
||||||
<xs:element name="content-type-options">
|
<xs:element name="content-type-options">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
|
|
|
@ -384,6 +384,58 @@ public class HttpHeadersConfigTests {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestWhenSettingXssProtectionHeaderValueToZeroThenDefaultsToZero() throws Exception {
|
||||||
|
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||||
|
excludedHeaders.remove("X-XSS-Protection");
|
||||||
|
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionHeaderValueZero")).autowire();
|
||||||
|
// @formatter:off
|
||||||
|
this.mvc.perform(get("/"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(header().string("X-XSS-Protection", "0"))
|
||||||
|
.andExpect(excludes(excludedHeaders));
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestWhenSettingXssProtectionHeaderValueToOneThenDefaultsToOne() throws Exception {
|
||||||
|
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||||
|
excludedHeaders.remove("X-XSS-Protection");
|
||||||
|
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionHeaderValueOne")).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 requestWhenSettingXssProtectionHeaderValueToOneModeBlockThenDefaultsToOneModeBlock() throws Exception {
|
||||||
|
Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
|
||||||
|
excludedHeaders.remove("X-XSS-Protection");
|
||||||
|
this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionHeaderValueOneModeBlock")).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 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
|
@Test
|
||||||
public void configureWhenXssProtectionDisabledAndBlockSetThenAutowireFails() {
|
public void configureWhenXssProtectionDisabledAndBlockSetThenAutowireFails() {
|
||||||
assertThatExceptionOfType(BeanCreationException.class)
|
assertThatExceptionOfType(BeanCreationException.class)
|
||||||
|
@ -650,6 +702,13 @@ public class HttpHeadersConfigTests {
|
||||||
.withMessageContaining("block");
|
.withMessageContaining("block");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void configureWhenXssProtectionDisabledAndHeaderValueSpecifiedThenAutowireFails() {
|
||||||
|
assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(
|
||||||
|
() -> this.spring.configLocations(this.xml("XssProtectionDisabledSpecifyingHeaderValue")).autowire())
|
||||||
|
.withMessageContaining("header-value");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void configureWhenFrameOptionsDisabledAndPolicySpecifiedThenAutowireFails() {
|
public void configureWhenFrameOptionsDisabledAndPolicySpecifiedThenAutowireFails() {
|
||||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?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>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?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 header-value="1"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?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 header-value="1; mode=block"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?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 header-value="0"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?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>
|
||||||
|
<xss-protection disabled="true" header-value="1"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -578,6 +578,12 @@ 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.
|
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.
|
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.
|
||||||
|
|
||||||
|
|
||||||
[[nsa-xss-protection-parents]]
|
[[nsa-xss-protection-parents]]
|
||||||
=== Parent Elements of <xss-protection>
|
=== Parent Elements of <xss-protection>
|
||||||
|
|
|
@ -149,6 +149,15 @@ public final class XXssProtectionHeaderWriter implements HeaderWriter {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HeaderValue from(String headerValue) {
|
||||||
|
for (HeaderValue value : values()) {
|
||||||
|
if (value.toString().equals(headerValue)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.value;
|
return this.value;
|
||||||
|
|
Loading…
Reference in New Issue