Skip to content

Commit 0d38322

Browse files
Merge pull request #68 from contentstack/next
Next
2 parents b4c5f23 + 71fd54a commit 0d38322

File tree

3 files changed

+49
-28
lines changed

3 files changed

+49
-28
lines changed

Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
A brief description of what changes project contains
44

5+
## May 14, 2024
6+
7+
#### v1.2.9
8+
9+
- Fixed vulnerability issue related to strAttrs and children.
10+
511
## April 23, 2024
612

713
#### v1.2.8

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.contentstack.sdk</groupId>
66
<artifactId>utils</artifactId>
7-
<version>1.2.8</version>
7+
<version>1.2.9</version>
88
<packaging>jar</packaging>
99
<name>Contentstack-utils</name>
1010
<description>Java Utils SDK for Contentstack Content Delivery API, Contentstack is a headless CMS</description>
@@ -29,7 +29,7 @@
2929
<validation-version>2.0.1.Final</validation-version>
3030
<json-version>20240303</json-version>
3131
<spring-web-version>6.1.6</spring-web-version>
32-
<org.apache.commons-text>1.11.0</org.apache.commons-text>
32+
<org.apache.commons-text>1.12.0</org.apache.commons-text>
3333
</properties>
3434

3535
<developers>

src/main/java/com/contentstack/utils/render/DefaultOption.java

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import com.contentstack.utils.node.MarkType;
77
import org.apache.commons.text.StringEscapeUtils;
88
import org.json.JSONObject;
9+
import org.jsoup.Jsoup;
10+
import org.jsoup.nodes.Document;
911

1012
import java.util.*;
1113

@@ -101,67 +103,70 @@ private String escapeInjectHtml(JSONObject nodeObj, String nodeType) {
101103
public String renderNode(String nodeType, JSONObject nodeObject, NodeCallback callback) {
102104
String strAttrs = strAttrs(nodeObject);
103105
String children = callback.renderChildren(nodeObject.optJSONArray("children"));
106+
// Jsoup sanitization
107+
Document sanitizedChildren = Jsoup.parse(children);
108+
String cleanChildren = sanitizedChildren.body().html();
104109
switch (nodeType) {
105110
case "p":
106-
return "<p" + strAttrs + ">" + children + "</p>";
111+
return "<p" + strAttrs + ">" + cleanChildren + "</p>";
107112
case "a":
108-
return "<a" + strAttrs + " href=\"" + escapeInjectHtml(nodeObject, "href") + "\">" + children + "</a>";
113+
return "<a" + strAttrs + " href=\"" + escapeInjectHtml(nodeObject, "href") + "\">" + cleanChildren + "</a>";
109114
case "img":
110115
String assetLink = getNodeStr(nodeObject, "asset-link");
111116
if (!assetLink.isEmpty()) {
112117
JSONObject attrs = nodeObject.optJSONObject("attrs");
113118
if (attrs.has("link")) {
114-
return "<a href=\"" + escapeInjectHtml(nodeObject, "link") + "\" >" + "<img" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "asset-link") + "\" />" + children + "</a>";
119+
return "<a href=\"" + escapeInjectHtml(nodeObject, "link") + "\" >" + "<img" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "asset-link") + "\" />" + cleanChildren + "</a>";
115120
}
116-
return "<img" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "asset-link") + "\" />" + children;
121+
return "<img" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "asset-link") + "\" />" + cleanChildren;
117122
}
118-
return "<img" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "src") + "\" />" + children;
123+
return "<img" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "src") + "\" />" + cleanChildren;
119124
case "embed":
120-
return "<iframe" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "src") + "\"" + children + "</iframe>";
125+
return "<iframe" + strAttrs + " src=\"" + escapeInjectHtml(nodeObject, "src") + "\"" + cleanChildren + "</iframe>";
121126
case "h1":
122-
return "<h1" + strAttrs + ">" + children + "</h1>";
127+
return "<h1" + strAttrs + ">" + cleanChildren + "</h1>";
123128
case "h2":
124-
return "<h2" + strAttrs + ">" + children + "</h2>";
129+
return "<h2" + strAttrs + ">" + cleanChildren + "</h2>";
125130
case "h3":
126-
return "<h3" + strAttrs + ">" + children + "</h3>";
131+
return "<h3" + strAttrs + ">" + cleanChildren + "</h3>";
127132
case "h4":
128-
return "<h4" + strAttrs + ">" + children + "</h4>";
133+
return "<h4" + strAttrs + ">" + cleanChildren + "</h4>";
129134
case "h5":
130-
return "<h5" + strAttrs + ">" + children + "</h5>";
135+
return "<h5" + strAttrs + ">" + cleanChildren + "</h5>";
131136
case "h6":
132-
return "<h6" + strAttrs + ">" + children + "</h6>";
137+
return "<h6" + strAttrs + ">" + cleanChildren + "</h6>";
133138
case "ol":
134-
return "<ol" + strAttrs + ">" + children + "</ol>";
139+
return "<ol" + strAttrs + ">" + cleanChildren + "</ol>";
135140
case "ul":
136-
return "<ul" + strAttrs + ">" + children + "</ul>";
141+
return "<ul" + strAttrs + ">" + cleanChildren + "</ul>";
137142
case "li":
138-
return "<li" + strAttrs + ">" + children + "</li>";
143+
return "<li" + strAttrs + ">" + cleanChildren + "</li>";
139144
case "hr":
140145
return "<hr" + strAttrs + " />";
141146
case "table":
142-
return "<table " + strAttrs + ">" + children + "</table>";
147+
return "<table " + strAttrs + ">" + cleanChildren + "</table>";
143148
case "thead":
144-
return "<thead " + strAttrs + ">" + children + "</thead>";
149+
return "<thead " + strAttrs + ">" + cleanChildren + "</thead>";
145150
case "tbody":
146-
return "<tbody" + strAttrs + ">" + children + "</tbody>";
151+
return "<tbody" + strAttrs + ">" + cleanChildren + "</tbody>";
147152
case "tfoot":
148-
return "<tfoot" + strAttrs + ">" + children + "</tfoot>";
153+
return "<tfoot" + strAttrs + ">" + cleanChildren + "</tfoot>";
149154
case "tr":
150-
return "<tr" + strAttrs + ">" + children + "</tr>";
155+
return "<tr" + strAttrs + ">" + cleanChildren + "</tr>";
151156
case "th":
152-
return "<th" + strAttrs + ">" + children + "</th>";
157+
return "<th" + strAttrs + ">" + cleanChildren + "</th>";
153158
case "td":
154-
return "<td" + strAttrs + ">" + children + "</td>";
159+
return "<td" + strAttrs + ">" + cleanChildren + "</td>";
155160
case "blockquote":
156-
return "<blockquote" + strAttrs + ">" + children + "</blockquote>";
161+
return "<blockquote" + strAttrs + ">" + cleanChildren + "</blockquote>";
157162
case "code":
158-
return "<code" + strAttrs + ">" + children + "</code>";
163+
return "<code" + strAttrs + ">" + cleanChildren + "</code>";
159164
case "reference":
160165
return "";
161166
case "fragment":
162-
return "<fragment" + strAttrs + ">" + children + "</fragment>";
167+
return "<fragment" + strAttrs + ">" + cleanChildren + "</fragment>";
163168
default:
164-
return children;
169+
return cleanChildren;
165170
}
166171
}
167172

@@ -182,6 +187,16 @@ String strAttrs(JSONObject nodeObject) {
182187
for (String key : attrsObject.keySet()) {
183188
Object objValue = attrsObject.opt(key);
184189
String value = objValue.toString();
190+
191+
StringBuilder escapedValue = new StringBuilder();
192+
for (char ch : value.toCharArray()) {
193+
if (ch == '&' || ch == '<' || ch == '>' || ch == '"' || ch == '\'') {
194+
escapedValue.append("&#").append((int) ch).append(';');
195+
} else {
196+
escapedValue.append(ch);
197+
}
198+
}
199+
value = escapedValue.toString();
185200
// If style is available, do styling calculations
186201
if (Objects.equals(key, "style")) {
187202
String resultStyle = stringifyStyles(attrsObject.optJSONObject("style"));

0 commit comments

Comments
 (0)