Skip to content

Commit ddcd1e5

Browse files
authored
Merge pull request #175 from contentstack/fix/DX-2268-Sre-code-vulnerability
fixes have been added
2 parents fff0227 + 760aeee commit ddcd1e5

File tree

8 files changed

+581
-199
lines changed

8 files changed

+581
-199
lines changed

src/main/java/com/contentstack/sdk/AssetLibrary.java

+46-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ protected void setStackInstance(@NotNull Stack stack) {
3131
this.headers = stack.headers;
3232
}
3333

34+
//Sanitization of keys
35+
private boolean isValidKey(String key) {
36+
return key.matches("^[a-zA-Z0-9_.]+$");
37+
}
38+
39+
//Sanitization of values
40+
private boolean isValidValue(Object value) {
41+
if(value instanceof String){
42+
return ((String) value).matches("^[a-zA-Z0-9_.\\-\\s]+$");
43+
}
44+
return true;
45+
}
46+
47+
//Sanitization of values list
48+
private boolean isValidValueList(Object[] values) {
49+
for (Object value : values) {
50+
if (value instanceof String) {
51+
if (!((String) value).matches("^[a-zA-Z0-9_.\\-\\s]+$")) {
52+
return false;
53+
}
54+
}
55+
}
56+
return true;
57+
}
58+
3459
/**
3560
* Sets header.
3661
*
@@ -151,7 +176,11 @@ public int getCount() {
151176
* </pre>
152177
*/
153178
public AssetLibrary addParam(@NotNull String paramKey, @NotNull Object paramValue) {
154-
urlQueries.put(paramKey, paramValue);
179+
if (isValidKey(paramKey) && isValidValue(paramValue)) {
180+
urlQueries.put(paramKey, paramValue);
181+
} else {
182+
logger.warning("Invalid key or value");
183+
}
155184
return this;
156185
}
157186

@@ -172,8 +201,12 @@ public AssetLibrary addParam(@NotNull String paramKey, @NotNull Object paramValu
172201
* </pre>
173202
*/
174203
public AssetLibrary removeParam(@NotNull String paramKey){
175-
if(urlQueries.has(paramKey)){
176-
urlQueries.remove(paramKey);
204+
if(isValidKey(paramKey)) {
205+
if(urlQueries.has(paramKey)){
206+
urlQueries.remove(paramKey);
207+
}
208+
} else {
209+
logger.warning("Invalid key");
177210
}
178211
return this;
179212
}
@@ -255,7 +288,9 @@ private HashMap<String, Object> getUrlParams(JSONObject urlQueriesJSON) {
255288
while (iter.hasNext()) {
256289
String key = iter.next();
257290
Object value = urlQueriesJSON.opt(key);
258-
hashMap.put(key, value);
291+
if(isValidKey(key) && isValidValue(value)) {
292+
hashMap.put(key, value);
293+
}
259294
}
260295
}
261296
return hashMap;
@@ -311,9 +346,13 @@ public enum ORDERBY {
311346
}
312347

313348
public AssetLibrary where(String key, String value) {
314-
JSONObject queryParams= new JSONObject();
315-
queryParams.put(key,value);
316-
urlQueries.put("query", queryParams);
349+
if(isValidKey(key) && isValidValue(value)){
350+
JSONObject queryParams = new JSONObject();
351+
queryParams.put(key,value);
352+
urlQueries.put("query", queryParams);
353+
} else {
354+
throw new IllegalArgumentException("Invalid key or value");
355+
}
317356
return this;
318357
}
319358

src/main/java/com/contentstack/sdk/AssetsModel.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ class AssetsModel {
2020
*/
2121
public AssetsModel(JSONObject response) {
2222
JSONArray listResponse = null;
23-
Object rawAssets = response.get("assets"); // Get assets
23+
Object rawAssets = response.opt("assets"); // Get assets
2424
if (rawAssets instanceof List) { // Check if it's an ArrayList
2525
List<?> assetsList = (List<?>) rawAssets;
2626
listResponse = new JSONArray(assetsList); // Convert to JSONArray
27+
} else if (rawAssets != null) {
28+
throw new IllegalArgumentException("Invalid type for 'assets' key: " + rawAssets.getClass().getName());
2729
}
2830
if (listResponse != null) {
2931
listResponse.forEach(model -> {

src/main/java/com/contentstack/sdk/CSConnectionRequest.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public void setParams(Object... objects) {
8383
}
8484

8585
@Override
86-
public void sendRequest() {
86+
public synchronized void sendRequest() {
8787
CSHttpConnection connection = new CSHttpConnection(urlToCall, this);
8888
connection.setController(controller);
8989
connection.setHeaders(header);
@@ -99,7 +99,7 @@ public void sendRequest() {
9999
}
100100

101101
@Override
102-
public void onRequestFailed(JSONObject error, int statusCode, ResultCallBack callBackObject) {
102+
public synchronized void onRequestFailed(JSONObject error, int statusCode, ResultCallBack callBackObject) {
103103
Error errResp = new Error();
104104
if (error.has(ERROR_MESSAGE)) {
105105
String errMsg = error.optString(ERROR_MESSAGE);
@@ -119,7 +119,7 @@ public void onRequestFailed(JSONObject error, int statusCode, ResultCallBack cal
119119
}
120120

121121
@Override
122-
public void onRequestFinished(CSHttpConnection request) {
122+
public synchronized void onRequestFinished(CSHttpConnection request) {
123123
JSONObject jsonResponse = request.getResponse();
124124
if (request.getController().equalsIgnoreCase(Constants.QUERYOBJECT)) {
125125
EntriesModel model = new EntriesModel(jsonResponse);

src/main/java/com/contentstack/sdk/ContentTypesModel.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ public void setJSON(JSONObject responseJSON) {
2020
if (responseJSON != null) {
2121
String ctKey = "content_type";
2222
if (responseJSON.has(ctKey) && responseJSON.opt(ctKey) instanceof LinkedHashMap) {
23-
this.response = new JSONObject((LinkedHashMap<?, ?>) responseJSON.get(ctKey));
23+
try {
24+
this.response = new JSONObject((LinkedHashMap<?, ?>) responseJSON.get(ctKey));
25+
} catch (Exception e) {
26+
System.err.println("Error processing 'content_type': " + e.getMessage());
27+
}
2428
}
2529
String ctListKey = "content_types";
2630
if (responseJSON.has(ctListKey) && responseJSON.opt(ctListKey) instanceof ArrayList) {
31+
try {
2732
ArrayList<LinkedHashMap<?, ?>> contentTypes = (ArrayList) responseJSON.get(ctListKey);
2833
List<Object> objectList = new ArrayList<>();
2934
if (!contentTypes.isEmpty()) {
@@ -32,13 +37,18 @@ public void setJSON(JSONObject responseJSON) {
3237
// Convert LinkedHashMap to JSONObject
3338
JSONObject jsonModel = new JSONObject((LinkedHashMap<?, ?>) model);
3439
objectList.add(jsonModel);
40+
} else {
41+
System.err.println("Invalid type in 'content_types' list. Expected LinkedHashMap.");
3542
}
3643
});
3744
}
3845
this.response = new JSONArray(objectList);
3946
this.responseJSONArray = new JSONArray(objectList);
40-
}
47+
} catch (Exception e) {
48+
System.err.println("Error processing 'content_types': " + e.getMessage());
4149
}
50+
}
51+
}
4252
}
4353

4454
public Object getResponse() {

src/main/java/com/contentstack/sdk/EntryModel.java

+40-19
Original file line numberDiff line numberDiff line change
@@ -46,29 +46,47 @@ public EntryModel(JSONObject response) {
4646
}
4747

4848
if (this.jsonObject.has(UID_KEY)) {
49-
this.uid = (String) this.jsonObject.opt(UID_KEY);
49+
this.uid = this.jsonObject.optString(UID_KEY, null);
5050
}
5151
if (this.jsonObject.has(TITLE_KEY)) {
52-
this.title = (String) this.jsonObject.opt(TITLE_KEY);
52+
this.title = this.jsonObject.optString(TITLE_KEY, null);
5353
}
5454
if (this.jsonObject.has(LOCALE_KEY)) {
55-
this.language = (String) this.jsonObject.opt(LOCALE_KEY);
55+
this.language = this.jsonObject.optString(LOCALE_KEY,null);
5656
}
5757
if (this.jsonObject.has(URL_KEY)) {
58-
this.url = (String) this.jsonObject.opt(URL_KEY);
58+
this.url = this.jsonObject.optString(URL_KEY,null);
5959
}
6060
if (this.jsonObject.has("description")) {
61-
this.description = this.jsonObject.opt("description");
62-
}
63-
this.images = (JSONArray) this.jsonObject.opt("images");
64-
this.isDirectory = (Boolean) this.jsonObject.opt("is_dir");
65-
this.updatedAt = (String) this.jsonObject.opt("updated_at");
66-
this.updatedBy = (String) this.jsonObject.opt("updated_by");
67-
this.createdAt = (String) this.jsonObject.opt("created_at");
68-
this.createdBy = (String) this.jsonObject.opt("created_by");
69-
this.locale = (String) this.jsonObject.opt(LOCALE_KEY);
70-
this.inProgress = (Boolean) this.jsonObject.opt("_in_progress");
71-
this.version = this.jsonObject.opt("_version") != null ? (int) this.jsonObject.opt("_version") : 1;
61+
this.description = this.jsonObject.optString("description");
62+
}
63+
if(this.jsonObject.has("images") && this.jsonObject.opt("images") instanceof JSONArray) {
64+
this.images = this.jsonObject.optJSONArray("images");
65+
}
66+
if(this.jsonObject.has("is_dir") && this.jsonObject.opt("is_dir") instanceof Boolean) {
67+
this.isDirectory = this.jsonObject.optBoolean("is_dir");
68+
}
69+
if(this.jsonObject.has("updated_at")) {
70+
this.updatedAt = this.jsonObject.optString("updated_at");
71+
}
72+
if(this.jsonObject.has("updated_by")) {
73+
this.updatedBy = this.jsonObject.optString("updated_by");
74+
}
75+
if(this.jsonObject.has("created_at")) {
76+
this.createdAt = this.jsonObject.optString("created_at");
77+
}
78+
if(this.jsonObject.has("created_by")) {
79+
this.createdBy = this.jsonObject.optString("created_by");
80+
}
81+
if(this.jsonObject.has(LOCALE_KEY)) {
82+
this.locale = this.jsonObject.optString(LOCALE_KEY);
83+
}
84+
if(this.jsonObject.has("_in_progress") && this.jsonObject.opt("_in_progress") instanceof Boolean) {
85+
this.inProgress = this.jsonObject.optBoolean("_in_progress");
86+
}
87+
if(this.jsonObject.has("_version") && this.jsonObject.opt("_version") instanceof Integer) {
88+
this.version = this.jsonObject.optInt("_version",1);
89+
}
7290
if (this.jsonObject.has(PUBLISH_DETAIL_KEY)) {
7391
parsePublishDetail();
7492
}
@@ -77,12 +95,15 @@ public EntryModel(JSONObject response) {
7795

7896
private void parsePublishDetail() {
7997
if (this.jsonObject.opt(PUBLISH_DETAIL_KEY) instanceof JSONObject) {
80-
this.publishDetails = (JSONObject) this.jsonObject.opt(PUBLISH_DETAIL_KEY);
81-
this.environment = this.publishDetails.optString("environment");
82-
this.time = this.publishDetails.optString("time");
83-
this.user = this.publishDetails.optString("user");
98+
this.publishDetails = this.jsonObject.optJSONObject(PUBLISH_DETAIL_KEY);
99+
if(this.publishDetails != null) {
100+
this.environment = this.publishDetails.optString("environment");
101+
this.time = this.publishDetails.optString("time");
102+
this.user = this.publishDetails.optString("user");
103+
}
84104
}
85105
this.metadata = new HashMap<>();
86106
this.metadata.put(PUBLISH_DETAIL_KEY, this.publishDetails);
87107
}
88108
}
109+

0 commit comments

Comments
 (0)