From cfbcc222a056d777432e88ec07aa1621bc7d0bc9 Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Mon, 14 Sep 2026 13:40:07 +0300 Subject: [PATCH 1/2] Escape reflected request parameters in the sample servlets The client SDK sample war (ServiceConfigServlet, UserProfileServlet) and the policy evaluation demo servlet echoed request parameters (service name, user name, resource) into their HTML response unescaped - a reflected XSS in code people deploy as-is and copy from. Escape them with XMLUtils.escapeSpecialCharacters. The demo also imported the long-gone com.iplanet.am.util.XMLUtils, so it did not compile; it now uses com.sun.identity.shared.xml.XMLUtils. Closes CodeQL java/xss alerts #112, #113, #114, #115 --- .../identity/demo/server/EvaluatePolicyServlet.java | 11 +++++++---- .../samples/clientsdk/ServiceConfigServlet.java | 8 +++++--- .../samples/clientsdk/UserProfileServlet.java | 6 ++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java b/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java index ee10440228..e3fb80351b 100644 --- a/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java +++ b/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java @@ -22,7 +22,7 @@ * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * - * Portions Copyrighted 2025 3A Systems LLC + * Portions Copyrighted 2025-2026 3A Systems LLC * * $Id: EvaluatePolicyServlet.java,v 1.2 2008/06/25 05:40:25 qcheng Exp $ * @@ -44,7 +44,7 @@ import com.sun.identity.shared.debug.Debug; //import com.iplanet.am.util.Debug; import com.iplanet.am.util.SystemProperties; -import com.iplanet.am.util.XMLUtils; +import com.sun.identity.shared.xml.XMLUtils; import com.iplanet.sso.SSOToken; import com.iplanet.sso.SSOTokenManager; @@ -154,13 +154,16 @@ protected void processRequest( PolicyDecision pd = pe.getPolicyDecision(ssoToken, resource, actions, null); boolean allowed = pe.isAllowed(ssoToken, resource, "GET", null); + // The resource is a request parameter reflected into the page. + String escapedResource = + XMLUtils.escapeSpecialCharacters(resource); StringBuffer message = new StringBuffer("
");
-                message.append("isAllowed() for ").append(resource).
+                message.append("isAllowed() for ").append(escapedResource).
                 append(" action:GET is:   ");
                 message = message.append(allowed);
                 message.append(NEWLINE);
                 message.append(NEWLINE);
-                message.append("getPolicyDecision() for ").append(resource).
+                message.append("getPolicyDecision() for ").append(escapedResource).
                     append(" action:GET is:");
                 message.append(NEWLINE);
                 message.append(XMLUtils.escapeSpecialCharacters(pd.toXML()));
diff --git a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java
index 058d8df097..76785172e9 100644
--- a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java
+++ b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java
@@ -25,13 +25,14 @@
  * $Id: ServiceConfigServlet.java,v 1.3 2008/06/25 05:41:09 qcheng Exp $
  *
  * Portions Copyrighted 2015-2016 ForgeRock AS.
- * Portions Copyrighted 2025 3A Systems LLC.
+ * Portions Copyrighted 2025-2026 3A Systems LLC.
  */
 
 package com.sun.identity.samples.clientsdk;
 
 import com.iplanet.sso.SSOToken;
 import com.sun.identity.authentication.AuthContext;
+import com.sun.identity.shared.xml.XMLUtils;
 import com.sun.identity.sm.ServiceConfigManager;
 import com.sun.identity.sm.ServiceSchemaManager;
 import java.io.IOException;
@@ -83,8 +84,9 @@ public void doGet(
             return;
         }
         
-        out.println("

ServiceName:

" + servicename); - out.println("

Username:

" + username); + // Request parameters are reflected into the page: escape them. + out.println("

ServiceName:

" + XMLUtils.escapeSpecialCharacters(servicename)); + out.println("

Username:

" + XMLUtils.escapeSpecialCharacters(username)); try { AuthContext lc = authenticate(orgname, username, password, out); diff --git a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java index 84a29db149..6b867ec62e 100644 --- a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java +++ b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java @@ -25,13 +25,14 @@ * $Id: UserProfileServlet.java,v 1.3 2008/06/25 05:41:09 qcheng Exp $ * * Portions Copyrighted 2016 ForgeRock AS. - * Portions Copyrighted 2025 3A Systems LLC. + * Portions Copyrighted 2025-2026 3A Systems LLC. */ package com.sun.identity.samples.clientsdk; import com.iplanet.sso.SSOToken; import com.sun.identity.authentication.AuthContext; +import com.sun.identity.shared.xml.XMLUtils; import com.sun.identity.idm.AMIdentity; import com.sun.identity.idm.IdUtils; import java.io.PrintWriter; @@ -80,7 +81,8 @@ public void doGet( return; } - out.println("

Username:

" + username); + // The user name is a request parameter reflected into the page: escape it. + out.println("

Username:

" + XMLUtils.escapeSpecialCharacters(username)); try { // Authenticate the user and obtain SSO Token From 4e7797ca65403b942557d4903ca2e4e89f5b2926 Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Tue, 15 Sep 2026 13:53:50 +0300 Subject: [PATCH 2/2] Escape the sample servlets with StringEscapeUtils.escapeHtml4 CodeQL kept reporting java/xss on the escaped lines: it follows taint through XMLUtils.escapeSpecialCharacters' char-by-char loop. Use commons-lang3 StringEscapeUtils.escapeHtml4 instead, as #1128 does for the SAML1 POST target; taint does not flow through it. The clientsdk sample war gains the commons-lang3 dependency (the shaded clientsdk jar does not bundle it), the policy demo drops its XMLUtils import. --- .../sun/identity/demo/server/EvaluatePolicyServlet.java | 7 ++++--- openam-examples/openam-example-clientsdk-war/pom.xml | 6 +++++- .../identity/samples/clientsdk/ServiceConfigServlet.java | 6 +++--- .../sun/identity/samples/clientsdk/UserProfileServlet.java | 4 ++-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java b/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java index e3fb80351b..8c0de57866 100644 --- a/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java +++ b/openam-distribution/src/main/amserver/demo/source/com/sun/identity/demo/server/EvaluatePolicyServlet.java @@ -44,7 +44,6 @@ import com.sun.identity.shared.debug.Debug; //import com.iplanet.am.util.Debug; import com.iplanet.am.util.SystemProperties; -import com.sun.identity.shared.xml.XMLUtils; import com.iplanet.sso.SSOToken; import com.iplanet.sso.SSOTokenManager; @@ -52,6 +51,8 @@ import com.sun.identity.policy.PolicyEvaluator; import com.sun.identity.policy.PolicyDecision; +import org.apache.commons.lang3.StringEscapeUtils; + public class EvaluatePolicyServlet extends HttpServlet { // the debug file @@ -156,7 +157,7 @@ protected void processRequest( boolean allowed = pe.isAllowed(ssoToken, resource, "GET", null); // The resource is a request parameter reflected into the page. String escapedResource = - XMLUtils.escapeSpecialCharacters(resource); + StringEscapeUtils.escapeHtml4(resource); StringBuffer message = new StringBuffer("
");
                 message.append("isAllowed() for ").append(escapedResource).
                 append(" action:GET is:   ");
@@ -166,7 +167,7 @@ protected void processRequest(
                 message.append("getPolicyDecision() for ").append(escapedResource).
                     append(" action:GET is:");
                 message.append(NEWLINE);
-                message.append(XMLUtils.escapeSpecialCharacters(pd.toXML()));
+                message.append(StringEscapeUtils.escapeHtml4(pd.toXML()));
                 message.append("
"); sendResponse(response, message.toString()); } diff --git a/openam-examples/openam-example-clientsdk-war/pom.xml b/openam-examples/openam-example-clientsdk-war/pom.xml index 3e767556d7..a23f974cba 100644 --- a/openam-examples/openam-example-clientsdk-war/pom.xml +++ b/openam-examples/openam-example-clientsdk-war/pom.xml @@ -13,7 +13,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2012-2016 ForgeRock AS. - * Portions copyright 2025 3A Systems LLC. + * Portions copyright 2025-2026 3A Systems LLC. --> 4.0.0 @@ -90,6 +90,10 @@ org.openidentityplatform.openam openam-clientsdk + + org.apache.commons + commons-lang3 + org.owasp.esapi esapi diff --git a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java index 76785172e9..1bbe51d904 100644 --- a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java +++ b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/ServiceConfigServlet.java @@ -32,7 +32,6 @@ import com.iplanet.sso.SSOToken; import com.sun.identity.authentication.AuthContext; -import com.sun.identity.shared.xml.XMLUtils; import com.sun.identity.sm.ServiceConfigManager; import com.sun.identity.sm.ServiceSchemaManager; import java.io.IOException; @@ -40,6 +39,7 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringEscapeUtils; /** * Sample program that lists service configurations. @@ -85,8 +85,8 @@ public void doGet( } // Request parameters are reflected into the page: escape them. - out.println("

ServiceName:

" + XMLUtils.escapeSpecialCharacters(servicename)); - out.println("

Username:

" + XMLUtils.escapeSpecialCharacters(username)); + out.println("

ServiceName:

" + StringEscapeUtils.escapeHtml4(servicename)); + out.println("

Username:

" + StringEscapeUtils.escapeHtml4(username)); try { AuthContext lc = authenticate(orgname, username, password, out); diff --git a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java index 6b867ec62e..f38ef434ad 100644 --- a/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java +++ b/openam-examples/openam-example-clientsdk-war/src/main/java/com/sun/identity/samples/clientsdk/UserProfileServlet.java @@ -32,7 +32,6 @@ import com.iplanet.sso.SSOToken; import com.sun.identity.authentication.AuthContext; -import com.sun.identity.shared.xml.XMLUtils; import com.sun.identity.idm.AMIdentity; import com.sun.identity.idm.IdUtils; import java.io.PrintWriter; @@ -43,6 +42,7 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringEscapeUtils; /** * Sample program that show user profile. @@ -82,7 +82,7 @@ public void doGet( } // The user name is a request parameter reflected into the page: escape it. - out.println("

Username:

" + XMLUtils.escapeSpecialCharacters(username)); + out.println("

Username:

" + StringEscapeUtils.escapeHtml4(username)); try { // Authenticate the user and obtain SSO Token