CVE-2018-25097: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability, which was classified as problematic, was found in Acumos Design Studio up to 2.0.7. Affected is an unknown function. The manipulation leads to cross site scripting. It is possible to launch the attack remotely. Upgrading to version 2.0.8 is able to address this issue. The name of the patch is 0df8a5e8722188744973168648e4c74c69ce67fd. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-249420.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2024-01-02T16:15Z
Repository: https://github.com/acumos/design-studio
Language: Java
Files changed: docs/release-notes.rst, ds-compositionengine/pom.xml, ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/ArtfactDetailsController.java, ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/SolutionController.java, ds-compositionengine/src/main/java/org/acumos/designstudio/ce/util/SanitizeUtils.java
Commit date: 2018-11-13 20:49:20 +0530
Commit message: Senitization for CSS Vulnerability

Issue-Id : ACUMOS-1650
Description : Senitization for CSS Vulnerability - Design Studio

Change-Id: If8fd4b9b06f884219d93881f7922421870de8e3d
Signed-off-by: Ramanaiah Pirla <RP00490596@techmahindra.com>

Diff: diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index eb4f433..5292e80 100644
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -25,10 +25,11 @@ Acumos docker registry.  The TOSCAGenerator Client library is published in the A
 repository as a jar file.
 
 1.40.3-SNAPSHOT, 2018-11-13
 ---------------------------
 * ACUMOS-1969 : Default CDS startup check interval too short, attempts too few; pls increase
+* ACUMOS-1650 : Senitization for CSS Vulnerability
 
 1.40.2-SNAPSHOT, 2018-10-12
 ---------------------------
 * ACUMOS-1886 : IST2 Design Studio fails to start due to exception in populatePublicModelCacheForMatching
 
diff --git a/ds-compositionengine/pom.xml b/ds-compositionengine/pom.xml
index b5d898d..c8a13fb 100644
--- a/ds-compositionengine/pom.xml
+++ b/ds-compositionengine/pom.xml
@@ -143,11 +143,16 @@
 		</dependency>
 		<dependency>
 			<groupId>com.github.docker-java</groupId>
 			<artifactId>docker-java</artifactId>
 			<version>3.0.10</version>
-		</dependency>		
+		</dependency>
+		<dependency>
+		 	<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
+		 	<artifactId>owasp-java-html-sanitizer</artifactId>
+		 	<version>20180219.1</version>
+		</dependency>	
 	</dependencies>
 	<build>
 		<resources>
 			<resource>
 				<directory>src/main/resources</directory>
diff --git a/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/ArtfactDetailsController.java b/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/ArtfactDetailsController.java
index 1d677d8..5fe8722 100644
--- a/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/ArtfactDetailsController.java
+++ b/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/ArtfactDetailsController.java
@@ -23,10 +23,11 @@ package org.acumos.designstudio.ce.controller;
 import javax.servlet.http.HttpServletResponse;
 
 import org.acumos.designstudio.ce.service.IAcumosCatalog;
 import org.acumos.designstudio.ce.util.EELFLoggerDelegator;
 import org.acumos.designstudio.ce.util.Properties;
+import org.acumos.designstudio.ce.util.SanitizeUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
@@ -64,11 +65,11 @@ public class ArtfactDetailsController {
 			@RequestParam(value = "solutionId", required = true) String solutionId,
 			@RequestParam(value = "version", required = true) String version, HttpServletResponse response) {
 		logger.debug(EELFLoggerDelegator.debugLogger, "fetchJsonTOSCA() : Begin");
 		String result = "";
 		try {
-			result = iacumosCatalog.readArtifact(userId, solutionId, version, props.getArtifactType().trim());
+			result = iacumosCatalog.readArtifact(userId, SanitizeUtils.sanitize(solutionId), version, props.getArtifactType().trim());
 			
 			if (result == null || result.isEmpty()) {
 				response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 				result = "Failed to fetch the TOSCA details for specified solutionId and version";				
 			}
@@ -100,11 +101,11 @@ public class ArtfactDetailsController {
 				" fetchProtoBufJSON() : Begin");
 
 		String resultTemplate = "{\"protobuf_json\" : %s,\n \"success\" : \"%s\",\n \"errorMessage\" : \"%s\"}";
 		String result = "";
 		try {
-			result = iacumosCatalog.readArtifact(userId, solutionId, version, props.getProtoArtifactType().trim());
+			result = iacumosCatalog.readArtifact(userId, SanitizeUtils.sanitize(solutionId), version, props.getProtoArtifactType().trim());
 
 			if (result != null && !result.isEmpty()) {
 				resultTemplate = String.format(resultTemplate, result, true, "");
 			} else {
 				resultTemplate = String.format(resultTemplate, result, false, "Unable to read protoBufFile");
diff --git a/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/SolutionController.java b/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/SolutionController.java
index 0c328fc..0bed4e6 100644
--- a/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/SolutionController.java
+++ b/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/controller/SolutionController.java
@@ -31,10 +31,11 @@ import org.acumos.designstudio.ce.service.ICompositeSolutionService;
 import org.acumos.designstudio.ce.service.ISolutionService;
 import org.acumos.designstudio.ce.util.ConfigurationProperties;
 import org.acumos.designstudio.ce.util.DSUtil;
 import org.acumos.designstudio.ce.util.EELFLoggerDelegator;
 import org.acumos.designstudio.ce.util.Properties;
+import org.acumos.designstudio.ce.util.SanitizeUtils;
 import org.acumos.designstudio.ce.vo.DSCompositeSolution;
 import org.acumos.designstudio.ce.vo.SuccessErrorMessage;
 import org.acumos.designstudio.ce.vo.cdump.DataConnector;
 import org.acumos.designstudio.ce.vo.cdump.Nodes;
 import org.acumos.designstudio.ce.vo.cdump.Property;
@@ -134,11 +135,11 @@ public class SolutionController {
 		DSCompositeSolution dscs = new DSCompositeSolution();
 
 		try {
 			dscs.setAuthor(userId);
 			dscs.setSolutionName(solutionName);
-			dscs.setSolutionId(solutionId);
+			dscs.setSolutionId(SanitizeUtils.sanitize(solutionId));
 			dscs.setVersion(version);
 			dscs.setOnBoarder(userId);
 			dscs.setDescription(description);
 			dscs.setProvider(props.getProvider());
 			dscs.setToolKit(props.getToolKit());
@@ -224,11 +225,11 @@ public class SolutionController {
 		try {
 
 			boolean validNode = validateNode(node);
 			if (validNode) {
 				if ((solutionId != null && version != null) || (null != cid)) {
-					results = solutionService.addNode(userId, solutionId, version, cid, node);
+					results = solutionService.addNode(userId, SanitizeUtils.sanitize(solutionId), version, cid, node);
 				} else {
 					results = "{\"error\": \"Either Cid or SolutionId and Version need to Pass\"}";
 				}
 			} else {
 				results = "{\"error\": \"JSON schema not valid, Please check the input JSON\"}";
@@ -294,11 +295,11 @@ public class SolutionController {
 			@RequestParam(value = "solutionId", required = true) String solutionId,
 			@RequestParam(value = "version", required = true) String version) {
 		logger.debug(EELFLoggerDelegator.debugLogger, " fetchJsonTOSCA()  : Begin");
 		String result;
 		try {
-			result = solutionService.readCompositeSolutionGraph(userId, solutionId, version);
+			result = solutionService.readCompositeSolutionGraph(userId, SanitizeUtils.sanitize(solutionId), version);
 		} catch (Exception e) {
 			logger.error(EELFLoggerDelegator.errorLogger, "Failed to read the ComposietSolution", e);
 			result = "";
 		}
 		logger.debug(EELFLoggerDelegator.debugLogger, " fetchJsonTOSCA()  : End");
@@ -359,11 +360,11 @@ public class SolutionController {
 				}
 				if(null != dataConnector.getSplitterMap()){
 					splitterMap = dataConnector.getSplitterMap();
 				}
 			}
-			result = solutionService.modifyNode(userId, solutionId, version, cid, nodeId, nodeName, ndata, fieldMap, databrokerMap, collatorMap, splitterMap);
+			result = solutionService.modifyNode(userId, SanitizeUtils.sanitize(solutionId), version, cid, nodeId, nodeName, ndata, fieldMap, databrokerMap, collatorMap, splitterMap);
 		} catch (Exception e) {
 			logger.error(EELFLoggerDelegator.errorLogger, "-------Exception in  modifyNode() -------", e);
 		}
 		logger.debug(EELFLoggerDelegator.debugLogger, "------- modifyNode() ------- : End");
 		return result;
@@ -379,11 +380,11 @@ public class SolutionController {
 			@RequestParam(value = "linkid", required = true) String linkId,
 			@RequestParam(value = "linkname", required = true) String linkName) {
 		String result = null;
 		logger.debug(EELFLoggerDelegator.debugLogger, " modifyLink()  : Begin");
 		try {
-			result = solutionService.modifyLink(userId, cid, solutionId, version, linkId, linkName);
+			result = solutionService.modifyLink(userId, cid, SanitizeUtils.sanitize(solutionId), version, linkId, linkName);
 		} catch (Exception e) {
 			logger.error(EELFLoggerDelegator.errorLogger, "Exception in  modifyLink() ", e);
 		}
 		logger.debug(EELFLoggerDelegator.debugLogger, " modifyLink()  : End");
 		return result;
@@ -399,11 +400,11 @@ public class SolutionController {
 		String result = "";
 		logger.debug(EELFLoggerDelegator.debugLogger, " deleteCompositeSolution()  : Begin");
 
 		try {
 
-			boolean deleted = compositeServiceImpl.deleteCompositeSolution(userId, solutionId, version);
+			boolean deleted = compositeServiceImpl.deleteCompositeSolution(userId, SanitizeUtils.sanitize(solutionId), version);
 			if (!deleted) {
 				result = String.format(resultTemplate, "false", "Requested Solution Not Found");
 			} else {
 				result = String.format(resultTemplate, "true", "");
 			}
@@ -427,11 +428,11 @@ public class SolutionController {
 		String resultTemplate = "{\"success\":\"%s\", \"errorMessage\":\"%s\"}";
 		if (null == userId && null == nodeId) {
 			result = String.format(resultTemplate, false, "Mandatory feild(s) missing");
 		} else {
 			try {
-				boolean deletedNode = solutionService.deleteNode(userId, solutionId, version, cid, nodeId);
+				boolean deletedNode = solutionService.deleteNode(userId, SanitizeUtils.sanitize(solutionId), version, cid, nodeId);
 				if (deletedNode) {
 					result = String.format(resultTemplate, true, "");
 				} else {
 					result = String.format(resultTemplate, false, "Invalid Node Id – not found");
 				}
@@ -452,11 +453,11 @@ public class SolutionController {
 			@RequestParam(value = "solutionVersion", required = false) String solutionVersion,
 			@RequestParam(value = "cid", required = false) String cid) {
 		logger.debug(EELFLoggerDelegator.debugLogger, " closeCompositeSolution(): Begin ");
 		String result = "";
 		try {
-			result = compositeServiceImpl.closeCompositeSolution(userId, solutionId, solutionVersion, cid);
+			result = compositeServiceImpl.closeCompositeSolution(userId, SanitizeUtils.sanitize(solutionId), solutionVersion, cid);
 		} catch (Exception e) {
 			logger.error(EELFLoggerDelegator.errorLogger, " Exception in closeCompositeSolution() ", e);
 		}
 		logger.debug(EELFLoggerDelegator.debugLogger, " closeCompositeSolution(): End ");
 		return result;
@@ -470,11 +471,11 @@ public class SolutionController {
 			@RequestParam(value = "solutionVersion", required = false) String solutionVersion,
 			@RequestParam(value = "cid", required = false) String cid) {
 		logger.debug(EELFLoggerDelegator.debugLogger, " clearCompositeSolution(): Begin ");
 		String result = "";
 		try {
-			result = compositeServiceImpl.clearCompositeSolution(userId, solutionId, solutionVersion, cid);
+			result = compositeServiceImpl.clearCompositeSolution(userId, SanitizeUtils.sanitize(solutionId), solutionVersion, cid);
 		} catch (Exception e) {
 			logger.error(EELFLoggerDelegator.errorLogger, " Exception in clearCompositeSolution() ", e);
 		}
 		logger.debug(EELFLoggerDelegator.debugLogger, " clearCompositeSolution(): End ");
 		return result;
@@ -541,11 +542,11 @@ public class SolutionController {
 			@RequestParam(value = "solutionId", required = true) String solutionId,
 			@RequestParam(value = "version", required = true) String version) {
 		logger.debug(EELFLoggerDelegator.debugLogger, "validateCompositeSolution() : Begin ");
 		String result = "";
 		try {
-			result = compositeServiceImpl.validateCompositeSolution(userId, solutionName, solutionId, version);
+			result = compositeServiceImpl.validateCompositeSolution(userId, solutionName, SanitizeUtils.sanitize(solutionId), version);
 			result = String.format(result);
 		} catch (Exception e) {
 			result = "{\"success\" : \"false\", \"errorDescription\" : \"Failed to Validate Composite Solution\"}";
 			result = String.format(result);
 			logger.debug(EELFLoggerDelegator.errorLogger, " Exception in validateCompositeSolution() ", e);
@@ -580,11 +581,11 @@ public class SolutionController {
 		try {
 			if (linkId != null && sourceNodeName != null && targetNodeName != null && targetNodeId != null
 					&& targetNodeCapabilityName != null) {
 
 				if (validateProperty(property)) {
-					linkAdded = solutionService.addLink(userId, solutionId, version, linkName, linkId, sourceNodeName,
+					linkAdded = solutionService.addLink(userId, SanitizeUtils.sanitize(solutionId), version, linkName, linkId, sourceNodeName,
 							sourceNodeId, targetNodeName, targetNodeId, sourceNodeRequirement, targetNodeCapabilityName,
 							cid, property);
 
 					if (linkAdded) {
 						result = String.format(resultTemplate, true, "");
@@ -682,11 +683,11 @@ public class SolutionController {
 		String resultTemplate = "{\"success\":\"%s\", \"errorMessage\":\"%s\"}";
 		if (null == userId && null == linkId) {
 			result = String.format(resultTemplate, false, "Mandatory feild(s) missing");
 		} else {
 			try {
-				boolean deletedLink = solutionService.deleteLink(userId, solutionId, version, cid, linkId);
+				boolean deletedLink = solutionService.deleteLink(userId, SanitizeUtils.sanitize(solutionId), version, cid, linkId);
 				if (deletedLink) {
 					result = String.format(resultTemplate, true, "");
 				} else {
 					result = String.format(resultTemplate, false, "Invalid Link Id – not found");
 				}
@@ -709,11 +710,11 @@ public class SolutionController {
 			)
 			throws AcumosException {
         SuccessErrorMessage successErrorMessage = null;
 		logger.debug(EELFLoggerDelegator.debugLogger, "setProbeIndicator() in SolutionController Begin");
         try {
-        	successErrorMessage = compositeServiceImpl.setProbeIndicator(userId, solutionId, version, cid,probeIndicator);
+        	successErrorMessage = compositeServiceImpl.setProbeIndicator(userId, SanitizeUtils.sanitize(solutionId), version, cid,probeIndicator);
 		}catch (Exception e) {
 			logger.error(EELFLoggerDelegator.errorLogger, "Exception in setProbeIndicator() in SolutionController", e);
 		}
 		logger.debug(EELFLoggerDelegator.debugLogger, "setProbeIndicator() in SolutionController End");
 		return successErrorMessage;
diff --git a/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/util/SanitizeUtils.java b/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/util/SanitizeUtils.java
new file mode 100644
index 0000000..6ef6a6d
--- /dev/null
+++ b/ds-compositionengine/src/main/java/org/acumos/designstudio/ce/util/SanitizeUtils.java
@@ -0,0 +1,40 @@
+/*-
+ * ===============LICENSE_START=======================================================
+ * Acumos
+ * ===================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ * ===================================================================================
+ * This Acumos software file is distributed by AT&T and Tech Mahindra
+ * 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
+ *  
+ * This file 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.
+ * ===============LICENSE_END=========================================================
+ */
+
+package org.acumos.designstudio.ce.util;
+
+import org.owasp.html.HtmlPolicyBuilder;
+import org.owasp.html.PolicyFactory;
+
+public class SanitizeUtils {
+
+	public static PolicyFactory genericPolicy = new HtmlPolicyBuilder()
+    	    .requireRelNofollowOnLinks()
+    	    .allowTextIn("@")
+    	    .toFactory();
+    	
+	public static String sanitize(String html) {
+		if(null == html){
+			return html;
+		}
+		return genericPolicy.sanitize(html);
+	}
+    	
+}

Vulnerable code: 		</dependency>		
			result = iacumosCatalog.readArtifact(userId, solutionId, version, props.getArtifactType().trim());
			result = iacumosCatalog.readArtifact(userId, solutionId, version, props.getProtoArtifactType().trim());
			dscs.setSolutionId(solutionId);
					results = solutionService.addNode(userId, solutionId, version, cid, node);
			result = solutionService.readCompositeSolutionGraph(userId, solutionId, version);
			result = solutionService.modifyNode(userId, solutionId, version, cid, nodeId, nodeName, ndata, fieldMap, databrokerMap, collatorMap, splitterMap);
			result = solutionService.modifyLink(userId, cid, solutionId, version, linkId, linkName);
			boolean deleted = compositeServiceImpl.deleteCompositeSolution(userId, solutionId, version);
				boolean deletedNode = solutionService.deleteNode(userId, solutionId, version, cid, nodeId);
			result = compositeServiceImpl.closeCompositeSolution(userId, solutionId, solutionVersion, cid);
			result = compositeServiceImpl.clearCompositeSolution(userId, solutionId, solutionVersion, cid);
			result = compositeServiceImpl.validateCompositeSolution(userId, solutionName, solutionId, version);
					linkAdded = solutionService.addLink(userId, solutionId, version, linkName, linkId, sourceNodeName,
				boolean deletedLink = solutionService.deleteLink(userId, solutionId, version, cid, linkId);
        	successErrorMessage = compositeServiceImpl.setProbeIndicator(userId, solutionId, version, cid,probeIndicator);
Fixed code: * ACUMOS-1650 : Senitization for CSS Vulnerability
		</dependency>
		<dependency>
		 	<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
		 	<artifactId>owasp-java-html-sanitizer</artifactId>
		 	<version>20180219.1</version>
		</dependency>	
import org.acumos.designstudio.ce.util.SanitizeUtils;
			result = iacumosCatalog.readArtifact(userId, SanitizeUtils.sanitize(solutionId), version, props.getArtifactType().trim());
			result = iacumosCatalog.readArtifact(userId, SanitizeUtils.sanitize(solutionId), version, props.getProtoArtifactType().trim());
import org.acumos.designstudio.ce.util.SanitizeUtils;
			dscs.setSolutionId(SanitizeUtils.sanitize(solutionId));
					results = solutionService.addNode(userId, SanitizeUtils.sanitize(solutionId), version, cid, node);
			result = solutionService.readCompositeSolutionGraph(userId, SanitizeUtils.sanitize(solutionId), version);
			result = solutionService.modifyNode(userId, SanitizeUtils.sanitize(solutionId), version, cid, nodeId, nodeName, ndata, fieldMap, databrokerMap, collatorMap, splitterMap);
			result = solutionService.modifyLink(userId, cid, SanitizeUtils.sanitize(solutionId), version, linkId, linkName);
			boolean deleted = compositeServiceImpl.deleteCompositeSolution(userId, SanitizeUtils.sanitize(solutionId), version);
				boolean deletedNode = solutionService.deleteNode(userId, SanitizeUtils.sanitize(solutionId), version, cid, nodeId);
			result = compositeServiceImpl.closeCompositeSolution(userId, SanitizeUtils.sanitize(solutionId), solutionVersion, cid);
			result = compositeServiceImpl.clearCompositeSolution(userId, SanitizeUtils.sanitize(solutionId), solutionVersion, cid);
			result = compositeServiceImpl.validateCompositeSolution(userId, solutionName, SanitizeUtils.sanitize(solutionId), version);
					linkAdded = solutionService.addLink(userId, SanitizeUtils.sanitize(solutionId), version, linkName, linkId, sourceNodeName,
				boolean deletedLink = solutionService.deleteLink(userId, SanitizeUtils.sanitize(solutionId), version, cid, linkId);
        	successErrorMessage = compositeServiceImpl.setProbeIndicator(userId, SanitizeUtils.sanitize(solutionId), version, cid,probeIndicator);
/*-
 * ===============LICENSE_START=======================================================
 * Acumos
 * ===================================================================================
 * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
 * ===================================================================================
 * This Acumos software file is distributed by AT&T and Tech Mahindra
 * 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
 *  
 * This file 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.
 * ===============LICENSE_END=========================================================
 */

package org.acumos.designstudio.ce.util;

import org.owasp.html.HtmlPolicyBuilder;
import org.owasp.html.PolicyFactory;

public class SanitizeUtils {

	public static PolicyFactory genericPolicy = new HtmlPolicyBuilder()
    	    .requireRelNofollowOnLinks()
    	    .allowTextIn("@")
    	    .toFactory();
    	
	public static String sanitize(String html) {
		if(null == html){
			return html;
		}
		return genericPolicy.sanitize(html);
	}
    	
}