From 4d8bec5d0a56dd8fefaf3783ed57ae65139525cc Mon Sep 17 00:00:00 2001
From: gchatz22 <44476526+gchatz22@users.noreply.github.com>
Date: Tue, 28 Jul 2020 16:52:50 +0300
Subject: [PATCH 1/5] Cspinterceptor (#2)
Support for CSP in Struts 2:
- Implements a CSP Interceptor that adds a nonce-based, strict-dynamic policy to HTTP responses.
- Implements custom JSP and FTL
diff --git a/core/src/main/resources/template/simple/script.ftl b/core/src/main/resources/template/simple/script.ftl
new file mode 100644
index 000000000..f16653257
--- /dev/null
+++ b/core/src/main/resources/template/simple/script.ftl
@@ -0,0 +1,63 @@
+<#--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+
+<#if parameters.nonce?has_content>
+ nonce="${parameters.nonce}"<#rt/>
+#if>
+<#if parameters.async?has_content>
+ <#if parameters.async=="true">
+ async<#rt/>
+ #if>
+#if>
+<#if parameters.charset?has_content>
+ charset="${parameters.charset}"<#rt/>
+#if>
+<#if parameters.defer?has_content>
+ <#if parameters.defer=="true">
+ defer<#rt/>
+ #if>
+#if>
+<#if parameters.src?has_content>
+ src="${parameters.src}"<#rt/>
+#if>
+<#if parameters.type?has_content>
+ type="${parameters.type}"<#rt/>
+#if>
+<#if parameters.name?has_content>
+ name="${parameters.name}"<#rt/>
+#if>
+<#if parameters.referrerpolicy?has_content>
+ referrerpolicy="${parameters.referrerpolicy}"<#rt/>
+#if>
+<#if parameters.nomodule?has_content>
+ <#if parameters.nomodule=="true">
+ nomodule<#rt/>
+ #if>
+#if>
+<#if parameters.integrity?has_content>
+ integrity="${parameters.integrity}"<#rt/>
+#if>
+<#if parameters.crossorigin?has_content>
+ crossorigin="${parameters.crossorigin}"<#rt/>
+#if>
+>
diff --git a/core/src/main/resources/template/xhtml/link.ftl b/core/src/main/resources/template/xhtml/link.ftl
new file mode 100644
index 000000000..5261e7b19
--- /dev/null
+++ b/core/src/main/resources/template/xhtml/link.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+-->
+<#include "/${parameters.templateDir}/simple/link.ftl" />
diff --git a/core/src/main/resources/template/xhtml/script.ftl b/core/src/main/resources/template/xhtml/script.ftl
new file mode 100644
index 000000000..2dc7d3fd8
--- /dev/null
+++ b/core/src/main/resources/template/xhtml/script.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+-->
+<#include "/${parameters.templateDir}/simple/script.ftl" />
diff --git a/core/src/site/resources/tags/link-attributes.html b/core/src/site/resources/tags/link-attributes.html
new file mode 100644
index 000000000..df5bb2d08
--- /dev/null
+++ b/core/src/site/resources/tags/link-attributes.html
@@ -0,0 +1,432 @@
+
+
+ Dynamic Attributes Allowed: true |
+
+
+ | |
+
+
+ Name |
+ Required |
+ Default |
+ Evaluated |
+ Type |
+ Description |
+
+
+ | accesskey |
+ false |
+ |
+ false |
+ String |
+ Set the html accesskey attribute on rendered html element |
+
+
+ | as |
+ false |
+ |
+ false |
+ String |
+ HTML link as attribute |
+
+
+ | class |
+ false |
+ |
+ false |
+ String |
+ The css class to use for element - it's an alias of cssClass attribute. |
+
+
+ | crossorigin |
+ false |
+ |
+ false |
+ String |
+ HTML link crossorigin attribute |
+
+
+ | cssClass |
+ false |
+ |
+ false |
+ String |
+ The css class to use for element |
+
+
+ | cssErrorClass |
+ false |
+ |
+ false |
+ String |
+ The css error class to use for element |
+
+
+ | cssErrorStyle |
+ false |
+ |
+ false |
+ String |
+ The css error style definitions for element to use |
+
+
+ | cssStyle |
+ false |
+ |
+ false |
+ String |
+ The css style definitions for element to use |
+
+
+ | disabled |
+ false |
+ |
+ false |
+ String |
+ Set the html disabled attribute on rendered html element |
+
+
+ | errorPosition |
+ false |
+ |
+ false |
+ String |
+ Define error position of form element (top|bottom) |
+
+
+ | href |
+ false |
+ |
+ false |
+ String |
+ HTML link href attribute |
+
+
+ | hreflang |
+ false |
+ |
+ false |
+ String |
+ HTML link hreflang attribute |
+
+
+ | id |
+ false |
+ |
+ false |
+ String |
+ HTML id attribute |
+
+
+ | javascriptTooltip |
+ false |
+ false |
+ false |
+ Boolean |
+ Use JavaScript to generate tooltips |
+
+
+ | key |
+ false |
+ |
+ false |
+ String |
+ Set the key (name, value, label) for this particular component |
+
+
+ | label |
+ false |
+ |
+ false |
+ String |
+ Label expression used for rendering an element specific label |
+
+
+ | labelSeparator |
+ false |
+ : |
+ false |
+ String |
+ String that will be appended to the label |
+
+
+ | labelposition |
+ false |
+ |
+ false |
+ String |
+ Define label position of form element (top/left) |
+
+
+ | media |
+ false |
+ |
+ false |
+ String |
+ HTML link media attribute |
+
+
+ | name |
+ false |
+ |
+ false |
+ String |
+ The name to set for element |
+
+
+ | onblur |
+ false |
+ |
+ false |
+ String |
+ Set the html onblur attribute on rendered html element |
+
+
+ | onchange |
+ false |
+ |
+ false |
+ String |
+ Set the html onchange attribute on rendered html element |
+
+
+ | onclick |
+ false |
+ |
+ false |
+ String |
+ Set the html onclick attribute on rendered html element |
+
+
+ | ondblclick |
+ false |
+ |
+ false |
+ String |
+ Set the html ondblclick attribute on rendered html element |
+
+
+ | onfocus |
+ false |
+ |
+ false |
+ String |
+ Set the html onfocus attribute on rendered html element |
+
+
+ | onkeydown |
+ false |
+ |
+ false |
+ String |
+ Set the html onkeydown attribute on rendered html element |
+
+
+ | onkeypress |
+ false |
+ |
+ false |
+ String |
+ Set the html onkeypress attribute on rendered html element |
+
+
+ | onkeyup |
+ false |
+ |
+ false |
+ String |
+ Set the html onkeyup attribute on rendered html element |
+
+
+ | onmousedown |
+ false |
+ |
+ false |
+ String |
+ Set the html onmousedown attribute on rendered html element |
+
+
+ | onmousemove |
+ false |
+ |
+ false |
+ String |
+ Set the html onmousemove attribute on rendered html element |
+
+
+ | onmouseout |
+ false |
+ |
+ false |
+ String |
+ Set the html onmouseout attribute on rendered html element |
+
+
+ | onmouseover |
+ false |
+ |
+ false |
+ String |
+ Set the html onmouseover attribute on rendered html element |
+
+
+ | onmouseup |
+ false |
+ |
+ false |
+ String |
+ Set the html onmouseup attribute on rendered html element |
+
+
+ | onselect |
+ false |
+ |
+ false |
+ String |
+ Set the html onselect attribute on rendered html element |
+
+
+ | referrerpolicy |
+ false |
+ |
+ false |
+ String |
+ HTML link referrerpolicy attribute |
+
+
+ | rel |
+ false |
+ |
+ false |
+ String |
+ HTML link rel attribute |
+
+
+ | requiredLabel |
+ false |
+ false |
+ false |
+ Boolean |
+ If set to true, the rendered element will indicate that input is required |
+
+
+ | requiredPosition |
+ false |
+ |
+ false |
+ String |
+ Define required position of required form element (left|right) |
+
+
+ | sizes |
+ false |
+ |
+ false |
+ String |
+ HTML link sizes attribute |
+
+
+ | style |
+ false |
+ |
+ false |
+ String |
+ The css style definitions for element to use - it's an alias of cssStyle attribute. |
+
+
+ | tabindex |
+ false |
+ |
+ false |
+ String |
+ Set the html tabindex attribute on rendered html element |
+
+
+ | template |
+ false |
+ |
+ false |
+ String |
+ The template (other than default) to use for rendering the element |
+
+
+ | templateDir |
+ false |
+ |
+ false |
+ String |
+ The template directory. |
+
+
+ | theme |
+ false |
+ |
+ false |
+ String |
+ The theme (other than default) to use for rendering the element |
+
+
+ | title |
+ false |
+ |
+ false |
+ String |
+ Set the html title attribute on rendered html element |
+
+
+ | tooltip |
+ false |
+ |
+ false |
+ String |
+ Set the tooltip of this particular component |
+
+
+ | tooltipConfig |
+ false |
+ |
+ false |
+ String |
+ Deprecated. Use individual tooltip configuration attributes instead. |
+
+
+ | tooltipCssClass |
+ false |
+ StrutsTTClassic |
+ false |
+ String |
+ CSS class applied to JavaScrip tooltips |
+
+
+ | tooltipDelay |
+ false |
+ Classic |
+ false |
+ String |
+ Delay in milliseconds, before showing JavaScript tooltips |
+
+
+ | tooltipIconPath |
+ false |
+ |
+ false |
+ String |
+ Icon path used for image that will have the tooltip |
+
+
+ | type |
+ false |
+ |
+ false |
+ String |
+ HTML link type attribute |
+
+
+ | value |
+ false |
+ |
+ false |
+ String |
+ Preset the value of input element. |
+
+
diff --git a/core/src/site/resources/tags/link-description.html b/core/src/site/resources/tags/link-description.html
new file mode 100644
index 000000000..90df50c4d
--- /dev/null
+++ b/core/src/site/resources/tags/link-description.html
@@ -0,0 +1 @@
+Link tag automatically adds nonces to link elements - should be used in combination with Struts' CSP Interceptor.
diff --git a/core/src/site/resources/tags/script-attributes.html b/core/src/site/resources/tags/script-attributes.html
new file mode 100644
index 000000000..c8e6cb992
--- /dev/null
+++ b/core/src/site/resources/tags/script-attributes.html
@@ -0,0 +1,440 @@
+
+
+ Dynamic Attributes Allowed: true |
+
+
+ | |
+
+
+ Name |
+ Required |
+ Default |
+ Evaluated |
+ Type |
+ Description |
+
+
+ | accesskey |
+ false |
+ |
+ false |
+ String |
+ Set the html accesskey attribute on rendered html element |
+
+
+ | async |
+ false |
+ |
+ false |
+ String |
+ HTML script async attribute |
+
+
+ | charset |
+ false |
+ |
+ false |
+ String |
+ HTML script charset attribute |
+
+
+ | class |
+ false |
+ |
+ false |
+ String |
+ The css class to use for element - it's an alias of cssClass attribute. |
+
+
+ | crossorigin |
+ false |
+ |
+ false |
+ String |
+ HTML script crossorigin attribute |
+
+
+ | cssClass |
+ false |
+ |
+ false |
+ String |
+ The css class to use for element |
+
+
+ | cssErrorClass |
+ false |
+ |
+ false |
+ String |
+ The css error class to use for element |
+
+
+ | cssErrorStyle |
+ false |
+ |
+ false |
+ String |
+ The css error style definitions for element to use |
+
+
+ | cssStyle |
+ false |
+ |
+ false |
+ String |
+ The css style definitions for element to use |
+
+
+ | defer |
+ false |
+ |
+ false |
+ String |
+ HTML script defer attribute |
+
+
+ | disabled |
+ false |
+ |
+ false |
+ String |
+ Set the html disabled attribute on rendered html element |
+
+
+ | errorPosition |
+ false |
+ |
+ false |
+ String |
+ Define error position of form element (top|bottom) |
+
+
+ | id |
+ false |
+ |
+ false |
+ String |
+ HTML id attribute |
+
+
+ | integrity |
+ false |
+ |
+ false |
+ String |
+ HTML script integrity attribute |
+
+
+ | javascriptTooltip |
+ false |
+ false |
+ false |
+ Boolean |
+ Use JavaScript to generate tooltips |
+
+
+ | key |
+ false |
+ |
+ false |
+ String |
+ Set the key (name, value, label) for this particular component |
+
+
+ | label |
+ false |
+ |
+ false |
+ String |
+ Label expression used for rendering an element specific label |
+
+
+ | labelSeparator |
+ false |
+ : |
+ false |
+ String |
+ String that will be appended to the label |
+
+
+ | labelposition |
+ false |
+ |
+ false |
+ String |
+ Define label position of form element (top/left) |
+
+
+ | name |
+ false |
+ |
+ false |
+ String |
+ The name to set for element |
+
+
+ | nomodule |
+ false |
+ |
+ false |
+ String |
+ HTML script nomodule attribute |
+
+
+ | onblur |
+ false |
+ |
+ false |
+ String |
+ Set the html onblur attribute on rendered html element |
+
+
+ | onchange |
+ false |
+ |
+ false |
+ String |
+ Set the html onchange attribute on rendered html element |
+
+
+ | onclick |
+ false |
+ |
+ false |
+ String |
+ Set the html onclick attribute on rendered html element |
+
+
+ | ondblclick |
+ false |
+ |
+ false |
+ String |
+ Set the html ondblclick attribute on rendered html element |
+
+
+ | onfocus |
+ false |
+ |
+ false |
+ String |
+ Set the html onfocus attribute on rendered html element |
+
+
+ | onkeydown |
+ false |
+ |
+ false |
+ String |
+ Set the html onkeydown attribute on rendered html element |
+
+
+ | onkeypress |
+ false |
+ |
+ false |
+ String |
+ Set the html onkeypress attribute on rendered html element |
+
+
+ | onkeyup |
+ false |
+ |
+ false |
+ String |
+ Set the html onkeyup attribute on rendered html element |
+
+
+ | onmousedown |
+ false |
+ |
+ false |
+ String |
+ Set the html onmousedown attribute on rendered html element |
+
+
+ | onmousemove |
+ false |
+ |
+ false |
+ String |
+ Set the html onmousemove attribute on rendered html element |
+
+
+ | onmouseout |
+ false |
+ |
+ false |
+ String |
+ Set the html onmouseout attribute on rendered html element |
+
+
+ | onmouseover |
+ false |
+ |
+ false |
+ String |
+ Set the html onmouseover attribute on rendered html element |
+
+
+ | onmouseup |
+ false |
+ |
+ false |
+ String |
+ Set the html onmouseup attribute on rendered html element |
+
+
+ | onselect |
+ false |
+ |
+ false |
+ String |
+ Set the html onselect attribute on rendered html element |
+
+
+ | openTemplate |
+ false |
+ |
+ false |
+ String |
+ Set template to use for opening the rendered html. |
+
+
+ | referrerpolicy |
+ false |
+ |
+ false |
+ String |
+ HTML script referrerpolicy attribute |
+
+
+ | requiredLabel |
+ false |
+ false |
+ false |
+ Boolean |
+ If set to true, the rendered element will indicate that input is required |
+
+
+ | requiredPosition |
+ false |
+ |
+ false |
+ String |
+ Define required position of required form element (left|right) |
+
+
+ | src |
+ false |
+ |
+ false |
+ String |
+ HTML script src attribute |
+
+
+ | style |
+ false |
+ |
+ false |
+ String |
+ The css style definitions for element to use - it's an alias of cssStyle attribute. |
+
+
+ | tabindex |
+ false |
+ |
+ false |
+ String |
+ Set the html tabindex attribute on rendered html element |
+
+
+ | template |
+ false |
+ |
+ false |
+ String |
+ The template (other than default) to use for rendering the element |
+
+
+ | templateDir |
+ false |
+ |
+ false |
+ String |
+ The template directory. |
+
+
+ | theme |
+ false |
+ |
+ false |
+ String |
+ The theme (other than default) to use for rendering the element |
+
+
+ | title |
+ false |
+ |
+ false |
+ String |
+ Set the html title attribute on rendered html element |
+
+
+ | tooltip |
+ false |
+ |
+ false |
+ String |
+ Set the tooltip of this particular component |
+
+
+ | tooltipConfig |
+ false |
+ |
+ false |
+ String |
+ Deprecated. Use individual tooltip configuration attributes instead. |
+
+
+ | tooltipCssClass |
+ false |
+ StrutsTTClassic |
+ false |
+ String |
+ CSS class applied to JavaScrip tooltips |
+
+
+ | tooltipDelay |
+ false |
+ Classic |
+ false |
+ String |
+ Delay in milliseconds, before showing JavaScript tooltips |
+
+
+ | tooltipIconPath |
+ false |
+ |
+ false |
+ String |
+ Icon path used for image that will have the tooltip |
+
+
+ | type |
+ false |
+ |
+ false |
+ String |
+ HTML script type attribute |
+
+
+ | value |
+ false |
+ |
+ false |
+ String |
+ Preset the value of input element. |
+
+
diff --git a/core/src/site/resources/tags/script-description.html b/core/src/site/resources/tags/script-description.html
new file mode 100644
index 000000000..462599590
--- /dev/null
+++ b/core/src/site/resources/tags/script-description.html
@@ -0,0 +1 @@
+Script tag automatically adds nonces to script blocks - should be used in combination with Struts' CSP Interceptor.
diff --git a/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java
new file mode 100644
index 000000000..504be8bb4
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/interceptor/CspInterceptorTest.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+package org.apache.struts2.interceptor;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import org.apache.logging.log4j.util.Strings;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.interceptor.csp.CspInterceptor;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.struts2.interceptor.csp.CspSettings.*;
+
+public class CspInterceptorTest extends StrutsInternalTestCase {
+
+ private final CspInterceptor interceptor = new CspInterceptor();
+ private final MockActionInvocation mai = new MockActionInvocation();
+ private final MockHttpServletRequest request = new MockHttpServletRequest();
+ private final MockHttpServletResponse response = new MockHttpServletResponse();
+ private final Map