Skip to content

Commit 4dce8d3

Browse files
committed
fix: code vulnerabilitiies
1 parent 5dc85d8 commit 4dce8d3

File tree

4 files changed

+46
-32
lines changed

4 files changed

+46
-32
lines changed

lib/src/base_query.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,9 @@ class BaseQuery {
156156
}
157157

158158
void where(String fieldUid, QueryOperation queryOperation) {
159-
if (fieldUid.isNotEmpty) {
160-
switch(queryOperation.operationType) {
159+
if (fieldUid.isNotEmpty && _isValidFieldUid(fieldUid)
160+
&& _isValidQueryValue(queryOperation.value)) {
161+
switch (queryOperation.operationType) {
161162
case QueryOperationType.Equals:
162163
parameter[fieldUid] = queryOperation.value;
163164
break;
@@ -191,4 +192,17 @@ class BaseQuery {
191192
}
192193
}
193194
}
195+
196+
bool _isValidFieldUid(String fieldUid) {
197+
final validFieldUidPattern = RegExp(r'^[a-zA-Z0-9-_.]+$');
198+
return validFieldUidPattern.hasMatch(fieldUid);
199+
}
200+
201+
bool _isValidQueryValue(dynamic value) {
202+
if (value is String) {
203+
final validValuePattern = RegExp(r'^[a-zA-Z0-9-_.]+$');
204+
return validValuePattern.hasMatch(value);
205+
}
206+
return true;
207+
}
194208
}

lib/src/entry_queryable.dart

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: lines_longer_than_80_chars
1+
// ignore_for_file: lines_longer_than_80_chars, unnecessary_lambdas
22

33
import 'package:contentstack/constant.dart';
44
import 'package:contentstack/src/enums/include.dart';
@@ -8,6 +8,11 @@ import 'package:contentstack/src/enums/include_type.dart';
88
class EntryQueryable {
99
Map<String, Object?> parameter = <String, Object?>{};
1010

11+
//sanitize
12+
String sanitizeInput(String input) {
13+
return input.replaceAll(RegExp(r'[^a-zA-Z0-9-_.]'), '');
14+
}
15+
1116
///
1217
/// This method adds key and value to an Entry.
1318
/// [key] The key as string which needs to be added to an Entry
@@ -43,10 +48,7 @@ class EntryQueryable {
4348
///
4449
void except(List<String> fieldUid) {
4550
if (fieldUid.isNotEmpty) {
46-
final List referenceArray = [];
47-
for (final item in fieldUid) {
48-
referenceArray.add(item);
49-
}
51+
final List<String> referenceArray = fieldUid.map((item) => sanitizeInput(item)).toList();
5052
parameter['except[BASE][]'] = referenceArray.toString();
5153
}
5254
}
@@ -171,15 +173,15 @@ class EntryQueryable {
171173
case IncludeType.None:
172174
if (referenceFieldUid.runtimeType == List) {
173175
for (var uid in referenceFieldUid) {
174-
referenceArray.add(uid);
176+
referenceArray.add(sanitizeInput(uid));
175177
}
176178
} else if (referenceFieldUid.runtimeType == String) {
177-
referenceArray.add(referenceFieldUid);
179+
referenceArray.add(sanitizeInput(referenceFieldUid));
178180
}
179181

180182
if (includeReferenceField.fieldUidList.isNotEmpty) {
181183
for (final item in includeReferenceField.fieldUidList) {
182-
referenceArray.add(item);
184+
referenceArray.add(sanitizeInput(item));
183185
}
184186
}
185187
parameter['include[]'] = referenceArray.toString();
@@ -188,7 +190,7 @@ class EntryQueryable {
188190
final Map<String, dynamic> referenceOnlyParam = <String, dynamic>{};
189191
if (includeReferenceField.fieldUidList.isNotEmpty) {
190192
for (final item in includeReferenceField.fieldUidList) {
191-
referenceArray.add(item);
193+
referenceArray.add(sanitizeInput(item));
192194
}
193195
}
194196
referenceOnlyParam[referenceFieldUid] = referenceArray;
@@ -199,7 +201,7 @@ class EntryQueryable {
199201
final Map<String, dynamic> referenceOnlyParam = <String, dynamic>{};
200202
if (includeReferenceField.fieldUidList.isNotEmpty) {
201203
for (final item in includeReferenceField.fieldUidList) {
202-
referenceArray.add(item);
204+
referenceArray.add(sanitizeInput(item));
203205
}
204206
}
205207
referenceOnlyParam[referenceFieldUid] = referenceArray;
@@ -262,10 +264,7 @@ class EntryQueryable {
262264
///
263265
void only(List<String> fieldUid) {
264266
if (fieldUid.isNotEmpty) {
265-
final List referenceArray = [];
266-
for (final item in fieldUid) {
267-
referenceArray.add(item);
268-
}
267+
final List<String> referenceArray = fieldUid.map((item) => sanitizeInput(item)).toList();
269268
parameter['only[BASE][]'] = referenceArray.toString();
270269
}
271270
}

lib/src/query_params.dart

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ class URLQueryParams {
55
// Appends a parameter to the query with received key.
66
void append(String key, dynamic value) {
77
if (value != null && value.toString().isNotEmpty) {
8-
_values[key] = Uri.encodeQueryComponent(value.toString());
8+
final sanitizedValue = _sanitizeInput(value.toString());
9+
_values[key] = Uri.encodeQueryComponent(sanitizedValue);
910
}
1011
}
1112

@@ -18,20 +19,22 @@ class URLQueryParams {
1819
// * param1=value1&param2=value2
1920
@override
2021
String toString() {
21-
String response = '';
22-
_values.forEach((key, value) {
23-
response += '$key=$value&';
24-
});
25-
return response.substring(0, response.isEmpty ? 0 : response.length - 1);
22+
return _values.entries
23+
.map((entry) => '${Uri.encodeQueryComponent(entry.key)}=${entry.value}')
24+
.join('&');
2625
}
2726

28-
String toUrl(String urls) {
29-
String updatedUrl;
30-
if (urls.isNotEmpty && urls.endsWith('/')) {
31-
updatedUrl = urls.substring(0, urls.length - 1);
32-
} else {
33-
updatedUrl = urls;
34-
}
35-
return '$updatedUrl?${toString()}';
27+
String toUrl(String url) {
28+
if (url.isEmpty) throw ArgumentError('URL cannot be empty');
29+
30+
final Uri parsedUri = Uri.parse(url);
31+
final String normalizedUrl = parsedUri.normalizePath().toString();
32+
33+
return Uri.parse('$normalizedUrl?${toString()}').toString();
34+
}
35+
36+
String _sanitizeInput(String input) {
37+
final pattern = RegExp(r'[<>\"\;(){}]');
38+
return input.replaceAll(pattern, '');
3639
}
3740
}

lib/src/stack.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,6 @@ class Stack {
463463
'authorization': headers!['authorization']!,
464464
'api_key': headers!['api_key']!,
465465
};
466-
467-
print('Request URL: $_url');
468466
await http.get(Uri.parse(_url), headers: _headers).then((response) {
469467
final Map bodyJson = json.decode(utf8.decode(response.bodyBytes));
470468
print(bodyJson);

0 commit comments

Comments
 (0)