Refactoring script and link elements for CSP nonce propagation

diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp
index 8de2f85..a8c8394 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp
@@ -27,14 +27,14 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Orders</title>
-    <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
-    <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
 
     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
-    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
-    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+    <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
     <![endif]-->
 </head>
 <body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp
index e576804..b7ce725 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp
@@ -27,14 +27,14 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Orders</title>
-    <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
-    <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
 
     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
-    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
-    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+    <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
     <![endif]-->
 </head>
 <body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp
index 2d9af8f..918c75d 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp
@@ -27,13 +27,13 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Orders</title>
-    <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
-    <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
-    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
-    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+    <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
     <![endif]-->
 </head>
 <body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp
index e96b57a..2b42d54 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp
@@ -27,14 +27,14 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Orders</title>
-    <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
-    <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
 
     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
-    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
-    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+    <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
     <![endif]-->
 </head>
 <body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp
index cfe3941..c947db0 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp
@@ -27,14 +27,14 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Orders</title>
-    <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
-    <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+    <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
 
     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
     <!--[if lt IE 9]>
-    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
-    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+    <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
     <![endif]-->
 </head>
 <body>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
index 1ae656a..0f0d4ed 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
@@ -63,26 +63,26 @@
 
     <title><decorator:title default="Struts2 Showcase"/></title>
 
-    <link href="<s:url value='/styles/bootstrap.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all">
-    <link href="<s:url value='/styles/main.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all"/>
+    <s:link href="<s:url value='/styles/bootstrap.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all">
+    <s:link href="<s:url value='/styles/main.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all"/>
 
-    <script src="<s:url value='/js/jquery-2.1.4.min.js' encode='false' includeParams='none'/>"></script>
-    <script src="<s:url value='/js/bootstrap.min.js' encode='false' includeParams='none'/>"></script>
-    <script type="text/javascript">
+    <s:script src="<s:url value='/js/jquery-2.1.4.min.js' encode='false' includeParams='none'/>"></s:script>
+    <s:script src="<s:url value='/js/bootstrap.min.js' encode='false' includeParams='none'/>"></s:script>
+    <s:script type="text/javascript">
         $(function () {
             var alerts = $('ul.alert').wrap('<div />');
             alerts.prepend('<a class="close" data-dismiss="alert" href="#">&times;</a>');
             alerts.alert();
         });
-    </script>
+    </s:script>
 
     <!-- Prettify -->
-    <link href="<s:url value='/styles/prettify.css' encode='false' includeParams='none'/>" rel="stylesheet">
-    <script src="<s:url value='/js/prettify.js' encode='false' includeParams='none'/>"></script>
+    <s:link href="<s:url value='/styles/prettify.css' encode='false' includeParams='none'/>" rel="stylesheet">
+    <s:script src="<s:url value='/js/prettify.js' encode='false' includeParams='none'/>"></s:script>
 
     <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
     <!--[if lt IE 9]>
-    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+    <s:script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></s:script>
     <![endif]-->
 
     <decorator:head/>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp
index fbfd233..3064aa2 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp
@@ -72,7 +72,7 @@
     </div>
 </div>
 
-<script type="text/javascript">
+<s:script type="text/javascript">
 /********************************************************************
  * JS just used on this page.
  * Usually this would be placed in a JS file
@@ -196,6 +196,6 @@
 $(window).bind('load', function() {
     $('form').bind('submit', ajaxFormValidation);
 });
-</script>
+</s:script>
 </body>
 </html>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp
index 2dc69b8..51d26e7 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp
@@ -26,10 +26,10 @@
 <head>
 	<title>Struts2 Showcase - Validation - DWR</title>
 	<s:head/>
-	<script type='text/javascript' src='../dwr/engine.js'></script>
-    <script type='text/javascript' src='../dwr/util.js'></script>
-	<script type='text/javascript' src='../dwr/interface/validator.js'></script>
-	<script type='text/javascript'>
+	<s:script type='text/javascript' src='../dwr/engine.js'></s:script>
+    <s:script type='text/javascript' src='../dwr/util.js'></s:script>
+	<s:script type='text/javascript' src='../dwr/interface/validator.js'></s:script>
+	<s:script type='text/javascript'>
         var dwrValidateReply = function(data) {
             var validationResult = '';
             for (index = 0; index < data.actionErrors.length; ++index) {
@@ -62,7 +62,7 @@
             validator.doPost('/validation', 'quizDwr', postData, dwrValidateReply);
             return false;
         }
-	</script>
+	</s:script>
 </head>
 
 <body>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp b/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp
index 5623c54..1255d2a 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp
@@ -64,11 +64,11 @@
 </div>
 
 
-<script>
+<s:script>
 	$('#codeTab a').click(function (e) {
 		e.preventDefault();
 		$(this).tab('show');
 	})
-</script>
+</s:script>
 </body>
 </html>
diff --git a/core/src/main/java/org/apache/struts2/components/Link.java b/core/src/main/java/org/apache/struts2/components/Link.java
index 4345c50..b766849 100644
--- a/core/src/main/java/org/apache/struts2/components/Link.java
+++ b/core/src/main/java/org/apache/struts2/components/Link.java
@@ -166,10 +166,5 @@
         if (title != null) {
             addParameter("title", findString(title));
         }
-
-        if (stack.getActionContext().getSession().containsKey("nonce")) {
-            String nonceValue = stack.getActionContext().getSession().get("nonce").toString();
-            addParameter("nonce", nonceValue);
-        }
     }
 }
diff --git a/core/src/main/java/org/apache/struts2/components/Script.java b/core/src/main/java/org/apache/struts2/components/Script.java
index f2a2081..447eaf7 100644
--- a/core/src/main/java/org/apache/struts2/components/Script.java
+++ b/core/src/main/java/org/apache/struts2/components/Script.java
@@ -168,11 +168,6 @@
         if (crossorigin != null) {
             addParameter("crossorigin", findString(crossorigin));
         }
-
-        if (stack.getActionContext().getSession().containsKey("nonce")) {
-            String nonceValue = stack.getActionContext().getSession().get("nonce").toString();
-            addParameter("nonce", nonceValue);
-        }
     }
 
 }
diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java
index 0e44a3b..f584f97 100644
--- a/core/src/main/java/org/apache/struts2/components/UIBean.java
+++ b/core/src/main/java/org/apache/struts2/components/UIBean.java
@@ -881,6 +881,15 @@
             }
         }
 
+        // to be used with the CSP interceptor - adds the nonce value as a parameter to be accessed from ftl files
+        Map<String, Object> session = stack.getActionContext().getSession();
+        if (session != null) {
+            if (session.containsKey("nonce")) {
+                String nonceValue = session.get("nonce").toString();
+                addParameter("nonce", nonceValue);
+            }
+        }
+
         evaluateExtraParams();
     }
 
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/LinkModel.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/LinkModel.java
new file mode 100644
index 0000000..f3fa7f5
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/LinkModel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.views.freemarker.tags;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.components.Component;
+import org.apache.struts2.components.Link;
+
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * @see Link
+ */
+public class LinkModel extends TagModel {
+    public LinkModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
+        super(stack, req, res);
+    }
+
+    protected Component getBean() {
+        return new Link(stack, req, res);
+    }
+}
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/ScriptModel.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/ScriptModel.java
new file mode 100644
index 0000000..c2a84f3
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/ScriptModel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.views.freemarker.tags;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.components.Component;
+import org.apache.struts2.components.Script;
+
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * @see Script
+ */
+public class ScriptModel extends TagModel {
+    public ScriptModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
+        super(stack, req, res);
+    }
+
+    protected Component getBean() {
+        return new Script(stack, req, res);
+    }
+}
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java
index 99c4686..819ba95 100644
--- a/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java
@@ -22,6 +22,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.components.Script;
 
 /**
  * Provides @s.tag access for various tags.
@@ -73,6 +74,8 @@
     protected ElseModel elseModel;
     protected ElseIfModel elseIfModel;
     protected InputTransferSelectModel inputtransferselect;
+    protected ScriptModel script;
+    protected LinkModel link;
 
 
     public StrutsModels(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
@@ -160,6 +163,14 @@
         return label;
     }
 
+    public LinkModel getLink() {
+        if (link == null) {
+            link = new LinkModel(stack, req, res);
+        }
+
+        return link;
+    }
+
     public PasswordModel getPassword() {
         if (password == null) {
             password = new PasswordModel(stack, req, res);
@@ -176,6 +187,14 @@
         return radio;
     }
 
+    public ScriptModel getScript() {
+        if (script == null) {
+            script = new ScriptModel(stack, req, res);
+        }
+
+        return script;
+    }
+
     public SelectModel getSelect() {
         if (select == null) {
             select = new SelectModel(stack, req, res);
diff --git a/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl b/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl
index 22a251b..91b0339 100644
--- a/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl
+++ b/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl
@@ -21,7 +21,9 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script type="text/javascript">
+    <script type="text/javascript" <#rt/>
+    <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+    >
     var baseUrl = "<@s.url value="/struts" includeParams="none"/>";
     window.open(baseUrl+"/webconsole.html", 'OGNL Console','width=500,height=450,status=no,toolbar=no,menubar=no');
     </script>    
diff --git a/core/src/main/resources/template/css_xhtml/head.ftl b/core/src/main/resources/template/css_xhtml/head.ftl
index d6c6d7f..df9916c 100644
--- a/core/src/main/resources/template/css_xhtml/head.ftl
+++ b/core/src/main/resources/template/css_xhtml/head.ftl
@@ -18,5 +18,7 @@
  * under the License.
  */
 -->
-<link rel="stylesheet" href="<@s.url value='/struts/css_xhtml/styles.css' includeParams='none' encode='false' />" type="text/css" />
+<link
+        <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+        rel="stylesheet" href="<@s.url value='/struts/css_xhtml/styles.css' includeParams='none' encode='false' />" type="text/css" />
 <#include "/${parameters.templateDir}/simple/head.ftl" />
diff --git a/core/src/main/resources/template/simple/combobox.ftl b/core/src/main/resources/template/simple/combobox.ftl
index 1a6d805..2f6f4a9 100644
--- a/core/src/main/resources/template/simple/combobox.ftl
+++ b/core/src/main/resources/template/simple/combobox.ftl
@@ -18,7 +18,9 @@
  * under the License.
  */
 -->
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
 	function autoPopulate_${parameters.escapedId}(targetElement) {
 		<#if parameters.headerKey?? && parameters.headerValue??>
 		if (targetElement.options[targetElement.selectedIndex].value == '${parameters.headerKey}') {
diff --git a/core/src/main/resources/template/simple/debug.ftl b/core/src/main/resources/template/simple/debug.ftl
index 7f007a7..145e5dd 100644
--- a/core/src/main/resources/template/simple/debug.ftl
+++ b/core/src/main/resources/template/simple/debug.ftl
@@ -18,7 +18,9 @@
  * under the License.
  */
 -->
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
 <!--
     function toggleDebug(debugId) {
         var debugDiv = document.getElementById(debugId);
diff --git a/core/src/main/resources/template/simple/doubleselect.ftl b/core/src/main/resources/template/simple/doubleselect.ftl
index 7e5bd41..3c913b6 100644
--- a/core/src/main/resources/template/simple/doubleselect.ftl
+++ b/core/src/main/resources/template/simple/doubleselect.ftl
@@ -70,7 +70,9 @@
     </#if>
         />
 </#if>
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+    <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
     <#assign itemCount = startCount/>
     var ${parameters.id}Group = new Array(${parameters.listSize} + ${startCount});
     for (var i = 0; i < (${parameters.listSize} + ${startCount}); i++) {
diff --git a/core/src/main/resources/template/simple/form-close-tooltips.ftl b/core/src/main/resources/template/simple/form-close-tooltips.ftl
index a84eb24..b5a5d30 100644
--- a/core/src/main/resources/template/simple/form-close-tooltips.ftl
+++ b/core/src/main/resources/template/simple/form-close-tooltips.ftl
@@ -24,7 +24,11 @@
 --><#t/>
 <#if (parameters.hasTooltip!false)><#t/>
 	<#lt/><!-- javascript that is needed for tooltips -->
-	<#lt/><script type="text/javascript" src='<@s.url value="/struts/domTT.js" includeParams="none" encode="false" />'></script>
-	<#lt/><link rel="stylesheet" type="text/css" href="<@s.url value="/struts/domTT.css" includeParams="none" encode="false" />"/>
+	<#lt/><script type="text/javascript" src='<@s.url value="/struts/domTT.js" includeParams="none" encode="false" />'<#rt/>
+	<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+	></script>
+	<#lt/><link rel="stylesheet" type="text/css" href="<@s.url value="/struts/domTT.css" includeParams="none" encode="false" />" <#rt/>
+	<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+	/>
 	
 </#if><#t/>
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/form-close.ftl b/core/src/main/resources/template/simple/form-close.ftl
index 0efea0c..469df76 100644
--- a/core/src/main/resources/template/simple/form-close.ftl
+++ b/core/src/main/resources/template/simple/form-close.ftl
@@ -21,16 +21,18 @@
 </form>
 
 <#if (parameters.customOnsubmitEnabled??)>
-<script type="text/javascript">
-<#-- 
-  Enable auto-select of optiontransferselect tag's entries upon containing form's 
+<script type="text/javascript" <#rt/>
+   <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
+<#--
+  Enable auto-select of optiontransferselect tag's entries upon containing form's
   submission.
 -->
 <#if (parameters.optiontransferselectIds!?size > 0)>
 	var containingForm = document.getElementById("${parameters.id}");
 	<#assign selectObjIds = parameters.optiontransferselectIds.keySet() />
 	<#list selectObjIds as selectObjectId>
-		StrutsUtils.addEventListener(containingForm, "submit", 
+		StrutsUtils.addEventListener(containingForm, "submit",
 			function(evt) {
 				var selectObj = document.getElementById("${selectObjectId}");
 				<#if parameters.optiontransferselectIds.get(selectObjectId)??>
@@ -62,7 +64,7 @@
 	var containingForm = document.getElementById("${parameters.id}");
 	<#assign selectDoubleObjIds = parameters.optiontransferselectDoubleIds.keySet() />
 	<#list selectDoubleObjIds as selectObjId>
-		StrutsUtils.addEventListener(containingForm, "submit", 
+		StrutsUtils.addEventListener(containingForm, "submit",
 			function(evt) {
 				var selectObj = document.getElementById("${selectObjId}");
 				<#if parameters.optiontransferselectDoubleIds.get(selectObjId)??>
@@ -84,7 +86,7 @@
 	var containingForm = document.getElementById("${parameters.id}");
 	<#assign tmpIds = parameters.updownselectIds.keySet() />
 	<#list tmpIds as tmpId>
-		StrutsUtils.addEventListener(containingForm, "submit", 
+		StrutsUtils.addEventListener(containingForm, "submit",
 			function(evt) {
 				var updownselectObj = document.getElementById("${tmpId}");
 				<#if parameters.updownselectIds.get(tmpId)??>
@@ -99,4 +101,4 @@
 </script>
 </#if>
 
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/form-close-tooltips.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/form-close-tooltips.ftl" />
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/head.ftl b/core/src/main/resources/template/simple/head.ftl
index 2c5484a..15d12f9 100644
--- a/core/src/main/resources/template/simple/head.ftl
+++ b/core/src/main/resources/template/simple/head.ftl
@@ -18,4 +18,6 @@
  * under the License.
  */
 -->
-<script src="${base}/struts/utils.js" type="text/javascript"></script>
\ No newline at end of file
+<script src="${base}/struts/utils.js" type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+></script>
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/inputtransferselect.ftl b/core/src/main/resources/template/simple/inputtransferselect.ftl
index 7428e05..4eacbbd 100644
--- a/core/src/main/resources/template/simple/inputtransferselect.ftl
+++ b/core/src/main/resources/template/simple/inputtransferselect.ftl
@@ -19,7 +19,9 @@
  */
 -->
 <#if !stack.findValue("#inputtransferselect_js_included")??><#t/>
-	<script type="text/javascript" src="<@s.url value="/struts/inputtransferselect.js" encode='false' includeParams='none'/>"></script>
+	<script type="text/javascript" src="<@s.url value="/struts/inputtransferselect.js" encode='false' includeParams='none'/>" <#rt/>
+	<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+	></script>
 	<#assign temporaryVariable = stack.setValue("#inputtransferselect_js_included", "true") /><#t/>
 </#if><#t/>
 <table>
diff --git a/core/src/main/resources/template/simple/link.ftl b/core/src/main/resources/template/simple/link.ftl
index 6bb0944..31821e0 100644
--- a/core/src/main/resources/template/simple/link.ftl
+++ b/core/src/main/resources/template/simple/link.ftl
@@ -20,7 +20,8 @@
 -->
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
-<link nonce="${parameters.nonce}"<#rt/>
+<link <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
 <#if parameters.href?has_content>
     href="${parameters.href}"<#rt/>
 </#if>
diff --git a/core/src/main/resources/template/simple/nonce.ftl b/core/src/main/resources/template/simple/nonce.ftl
new file mode 100644
index 0000000..a124cf6
--- /dev/null
+++ b/core/src/main/resources/template/simple/nonce.ftl
@@ -0,0 +1,23 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#if parameters.nonce?has_content>
+    nonce="${parameters.nonce}"<#rt/>
+</#if>
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/optiontransferselect.ftl b/core/src/main/resources/template/simple/optiontransferselect.ftl
index 40b03c9..d0b328b 100644
--- a/core/src/main/resources/template/simple/optiontransferselect.ftl
+++ b/core/src/main/resources/template/simple/optiontransferselect.ftl
@@ -19,7 +19,9 @@
  */
 -->
 <#if !stack.findValue("#optiontransferselect_js_included")??><#t/>
-	<script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>"></script>
+	<script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>"<#rt/>
+	<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+	></script>
 	<#assign temporaryVariable = stack.setValue("#optiontransferselect_js_included", "true") /><#t/>
 </#if><#t/>
 <table>
diff --git a/core/src/main/resources/template/simple/script.ftl b/core/src/main/resources/template/simple/script.ftl
index f166532..5afb30d 100644
--- a/core/src/main/resources/template/simple/script.ftl
+++ b/core/src/main/resources/template/simple/script.ftl
@@ -18,12 +18,10 @@
  * under the License.
  */
 -->
+<script <#rt/>
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
-<script <#rt/>
-<#if parameters.nonce?has_content>
- nonce="${parameters.nonce}"<#rt/>
-</#if>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
 <#if parameters.async?has_content>
  <#if parameters.async=="true">
   async<#rt/>
@@ -43,9 +41,6 @@
 <#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>
diff --git a/core/src/main/resources/template/simple/updownselect.ftl b/core/src/main/resources/template/simple/updownselect.ftl
index ad0a8ae..e8683fc 100644
--- a/core/src/main/resources/template/simple/updownselect.ftl
+++ b/core/src/main/resources/template/simple/updownselect.ftl
@@ -19,7 +19,9 @@
  */
 -->
 <#if !stack.findValue("#optiontransferselect_js_included")??><#t/>
-	<script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>"></script>
+	<script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>" <#rt/>
+	<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+	></script>
 	<#assign temporaryVariable = stack.setValue("#optiontransferselect_js_included", "true") /><#t/>
 </#if><#t/>
 <table>
diff --git a/core/src/main/resources/template/xhtml/form-close-validate.ftl b/core/src/main/resources/template/xhtml/form-close-validate.ftl
index 2cbb174..7fc1510 100644
--- a/core/src/main/resources/template/xhtml/form-close-validate.ftl
+++ b/core/src/main/resources/template/xhtml/form-close-validate.ftl
@@ -32,7 +32,9 @@
 END SNIPPET: supported-validators
 -->
 <#if ((parameters.validate!false == true) && (parameters.performValidation!false == true))>
-<script type="text/javascript">
+<script type="text/javascript"<#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
     function validateForm_${parameters.id?replace('[^a-zA-Z0-9_]', '_', 'r')}() {
         <#--
             In case of multiselect fields return only the first value.
diff --git a/core/src/main/resources/template/xhtml/form-close.ftl b/core/src/main/resources/template/xhtml/form-close.ftl
index 9b4d7ae..a220511 100644
--- a/core/src/main/resources/template/xhtml/form-close.ftl
+++ b/core/src/main/resources/template/xhtml/form-close.ftl
@@ -22,7 +22,9 @@
 <#include "/${parameters.templateDir}/simple/form-close.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/form-close-validate.ftl" />
 <#if parameters.focusElement??>
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
     StrutsUtils.addOnLoad(function() {
         var element = document.getElementById("${parameters.focusElement}");
         if(element) {
diff --git a/core/src/main/resources/template/xhtml/form-validate.ftl b/core/src/main/resources/template/xhtml/form-validate.ftl
index 5a65e0c..4e4cd6e 100644
--- a/core/src/main/resources/template/xhtml/form-validate.ftl
+++ b/core/src/main/resources/template/xhtml/form-validate.ftl
@@ -19,7 +19,9 @@
  */
 -->
 <#if parameters.validate!false == true>
-	<script type="text/javascript" src="${base}/struts/xhtml/validation.js"></script>
+	<script type="text/javascript" src="${base}/struts/xhtml/validation.js" <#rt/>
+    <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+	></script>
 	<#if parameters.onsubmit??>
 		${tag.addParameter('onsubmit', "${parameters.onsubmit}; return validateForm_${parameters.id?replace('[^a-zA-Z0-9_]', '_', 'r')}();")}
 	<#else>
diff --git a/core/src/main/resources/template/xhtml/head.ftl b/core/src/main/resources/template/xhtml/head.ftl
index 8bd9f55..61a7783 100644
--- a/core/src/main/resources/template/xhtml/head.ftl
+++ b/core/src/main/resources/template/xhtml/head.ftl
@@ -18,5 +18,7 @@
  * under the License.
  */
 -->
-<link rel="stylesheet" href="<@s.url value='/struts/xhtml/styles.css' includeParams='none' encode='false' />" type="text/css"/>
+<link rel="stylesheet" href="<@s.url value='/struts/xhtml/styles.css' includeParams='none' encode='false'/>" type="text/css"
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+/>
 <#include "/${parameters.templateDir}/simple/head.ftl" />
diff --git a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
index 9317397..3e8547e 100644
--- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
+++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
@@ -30,6 +30,7 @@
 
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 
 public class UIBeanTest extends StrutsInternalTestCase {
@@ -305,4 +306,20 @@
 
         assertEquals(cssStyle, txtFld.getParameters().get("cssStyle"));
     }
+
+    public void testNonce() {
+        String nonceVal = "r4nd0m";
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        MockHttpServletResponse res = new MockHttpServletResponse();
+        ActionContext actionContext = stack.getActionContext();
+        Map<String, Object> session = new HashMap<>();
+        session.put("nonce", nonceVal);
+        actionContext.withSession(session);
+
+        DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
+        dblSelect.evaluateParams();
+
+        assertEquals(nonceVal, dblSelect.getParameters().get("nonce"));
+    }
 }
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
index f7ef72a..a3f5027 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
@@ -73,6 +73,8 @@
         tag.setId("cb");
         tag.setList("collection");
 
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
         tag.doStartTag();
         tag.doEndTag();
 
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java
index bbee23b..fa47295 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java
@@ -48,10 +48,13 @@
 
     public void testDevModeEnabled() throws Exception {
         setDevMode(true);
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
 
         tag.doStartTag();
         tag.doEndTag();
         String result = writer.toString();
+
+        assertTrue("Nonce value not included", result.contains("nonce=\"r4nd0m\""));
         assertTrue(StringUtils.isNotEmpty(result));
         assertTrue("Property 'checkStackProperty' should be in Debug Tag output", StringUtils.contains(result, "<td>checkStackProperty</td>"));
     }
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java
index ff1a7d7..536a5d9 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java
@@ -87,13 +87,15 @@
         tag.setCssStyle("s1");
         tag.setDoubleCssClass("c2");
         tag.setDoubleCssStyle("s2");
-        
+
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
         tag.doStartTag();
         tag.doEndTag();
 
         verify(SelectTag.class.getResource("DoubleSelect-1.txt"));
     }
-    
+
     public void testOnchange() throws Exception {
         TestAction testAction = (TestAction) action;
 
@@ -151,7 +153,7 @@
         tag.setCssStyle("s1");
         tag.setDoubleCssClass("c2");
         tag.setDoubleCssStyle("s2");
-        
+
         tag.doStartTag();
         tag.doEndTag();
 
@@ -221,7 +223,7 @@
 
 
     }
-    
+
     public void testDoubleWithDotName() throws Exception {
         TestAction testAction = (TestAction) action;
 
@@ -377,4 +379,4 @@
             return key;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java
index 535e42f..1ccbb89 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java
@@ -61,6 +61,9 @@
         tag.setEnctype("myEncType");
         tag.setTitle("mytitle");
         tag.setOnsubmit("submitMe()");
+
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
         tag.doStartTag();
         tag.doEndTag();
         
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java
index a290f50..a0c0ff2 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java
@@ -32,7 +32,9 @@
     public void testHead1() throws Exception {
         HeadTag tag = new HeadTag();
         tag.setPageContext(pageContext);
-        
+
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
         tag.doStartTag();
         tag.doEndTag();
 
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java
index f2de3c0..ee60cd8 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java
@@ -42,6 +42,7 @@
 
         tag.setName("collection");
         tag.setList("collection");
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
 
         tag.doStartTag();
         tag.doEndTag();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java
index 56b7b78..d7e8bb1 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java
@@ -85,6 +85,8 @@
         tag.setDoubleHeaderKey("Double Header Key");
         tag.setDoubleHeaderValue("Double Header Value");
 
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
         tag.doStartTag();
         tag.doEndTag();
 
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java
index e020372..f35fa18 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java
@@ -60,6 +60,8 @@
         tag.setValue("mySelectedMapIds");
         tag.setEmptyOption("false");
 
+        stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
         tag.doStartTag();
         tag.doEndTag();
 
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
index fc3c1c0..0121ef4 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
@@ -1,7 +1,7 @@
 <tr>
     <td class="tdLabel"><label for="cb" class="label">mylabel:</label></td>
     <td class="tdInput">
-<script type="text/javascript">
+<script type="text/javascript" nonce="r4nd0m">
 	function autoPopulate_cb(targetElement) {
 		targetElement.form.elements['foo'].value=targetElement.options[targetElement.selectedIndex].value;
 	}
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt
index a641703..f5219cf 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt
@@ -8,7 +8,7 @@
 <br/>
 <select name="region" id="region" class="c2" style="s2">
 </select>
-<script type="text/javascript">
+<script type="text/javascript" nonce="r4nd0m">
     var fooGroup = new Array(2 + 0);
     for (var i = 0; i < (2 + 0); i++) {
     fooGroup[i] = [];
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt
index 9e30a79..d9c6359 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt
@@ -1,2 +1,2 @@
-<link rel="stylesheet" href="/struts/xhtml/styles.css" type="text/css"/>
-<script src="/struts/utils.js" type="text/javascript"></script>
\ No newline at end of file
+<link rel="stylesheet" href="/struts/xhtml/styles.css" type="text/css" nonce="r4nd0m"/>
+<script src="/struts/utils.js" type="text/javascript" nonce="r4nd0m"></script>
\ No newline at end of file
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt
index 22062bf..a73b85a 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt
@@ -1,7 +1,7 @@
 <tr>
   <td class="tdLabel"></td>
   <td class="tdInput">
-  <script type="text/javascript" src="/struts/inputtransferselect.js"></script>
+  <script type="text/javascript" src="/struts/inputtransferselect.js" nonce="r4nd0m"></script>
   <table>
   <tr><td><input type="text" name="collection_input" id="collection_input"/></td>
       <td class="tdTransferSelect"><inputtype="button"value="-&gt;"onclick="addOption(document.getElementById('collection_input'),document.getElementById('collection'))"/>
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt
index d423b3a..2ee3705 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt
@@ -1,7 +1,7 @@
 <tr> 
 <td class="tdLabel"></td> 
 <td class="tdInput">
-<script type="text/javascript" src="/struts/optiontransferselect.js"></script>
+<script type="text/javascript" src="/struts/optiontransferselect.js" nonce="r4nd0m"></script>
 <table>
 <tr>
 <td>
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt
index a00d294..0f8944b 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt
@@ -1,5 +1,5 @@
 <tr> <td class="tdLabel"></td> <td class="tdInput">
-<script type="text/javascript" src="/struts/optiontransferselect.js"></script>
+<script type="text/javascript" src="/struts/optiontransferselect.js" nonce="r4nd0m"></script>
 <table>
 <tr><td>
 <select name="myName" size="5" id="myId" multiple="multiple">
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java
index 4146592..55a7d35 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java
@@ -31,8 +31,7 @@
         Map<String, Object> params = context.getParameters();
         Attributes attrs = new Attributes();
 
-        attrs.add("nonce", (String) params.get("nonce"))
-                .addIfExists("href", params.get(("href")))
+        attrs.addIfExists("href", params.get(("href")))
                 .addIfExists("hreflang", params.get("hreflang"))
                 .addIfExists("rel", params.get("rel"))
                 .addIfExists("media", params.get("media"))
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/NonceHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/NonceHandler.java
new file mode 100644
index 0000000..aa75c2d
--- /dev/null
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/NonceHandler.java
@@ -0,0 +1,31 @@
+/*
+ * 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.views.java.simple;
+
+import org.apache.struts2.views.java.Attributes;
+import java.io.IOException;
+
+public class NonceHandler extends AbstractTagHandler {
+
+    @Override
+    public void start(String name, Attributes a) throws IOException {
+        a.addIfExists("nonce", context.getParameters().get("nonce"));
+        super.start(name, a);
+    }
+}
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java
index ec62941..34acef0 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java
@@ -33,13 +33,11 @@
         Map<String, Object> params = context.getParameters();
         Attributes attrs = new Attributes();
 
-        attrs.add("nonce", (String) params.get("nonce"))
-            .addIfExists("async", params.get("async"))
+        attrs.addIfExists("async", params.get("async"))
             .addIfExists("charset", params.get("charset"))
             .addIfExists("defer", params.get("defer"))
             .addIfExists("src", params.get("src"))
             .addIfExists("type", params.get("type"))
-            .addIfExists("name", params.get("name"))
             .addIfExists("referrerpolicy", params.get("referrerpolicy"))
             .addIfExists("nomodule", params.get("nomodule"))
             .addIfExists("integrity", params.get("integrity"))
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java
index 0e89630..adfc7f9 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java
@@ -37,7 +37,7 @@
                 put("datetextfield", new FactoryList(DateTextFieldHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class));
                 put("select", new FactoryList(SelectHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
                 put("form", new FactoryList(FormHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
-                put("form-close", new FactoryList(FormHandler.CloseHandler.class));
+                put("form-close", new FactoryList(FormHandler.CloseHandler.class, ScriptHandler.class, NonceHandler.class));
                 put("a", new FactoryList(AnchorHandler.class));
                 put("a-close", new FactoryList(AnchorHandler.CloseHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
                 put("checkbox", new FactoryList(CheckboxHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
@@ -50,13 +50,13 @@
                 put("textarea", new FactoryList(TextAreaHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
                 put("radiomap", new FactoryList(RadioHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
                 put("checkboxlist", new FactoryList(CheckboxListHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
-                put("script", new FactoryList(ScriptHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
+                put("script", new FactoryList(ScriptHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class, NonceHandler.class));
                 put("script-close", new FactoryList(ScriptHandler.CloseHandler.class));
-                put("link", new FactoryList(LinkHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
+                put("link", new FactoryList(LinkHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class, NonceHandler.class));
                 put("actionerror", new FactoryList(ActionErrorHandler.class));
                 put("token", new FactoryList(TokenHandler.class));
                 put("actionmessage", new FactoryList(ActionMessageHandler.class));
-                put("head", new FactoryList(HeadHandler.class));
+                put("head", new FactoryList(HeadHandler.class, NonceHandler.class));
                 put("hidden", new FactoryList(HiddenHandler.class));
                 put("fielderror", new FactoryList(FieldErrorHandler.class));
                 put("empty", new FactoryList(EmptyHandler.class));