mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 10:49:49 +08:00
Fix critical vulnerabilities: Remove sensitive logging, add JS validation, add security dependencies
Co-authored-by: animator <615622+animator@users.noreply.github.com>
This commit is contained in:
@@ -44,6 +44,36 @@ class JsRuntimeNotifier extends StateNotifier<JsRuntimeState> {
|
||||
late final JavascriptRuntime _runtime;
|
||||
String? _currentRequestId;
|
||||
|
||||
// Security: Maximum script length to prevent DoS attacks
|
||||
static const int _maxScriptLength = 50000; // 50KB
|
||||
|
||||
// Security: Dangerous JavaScript patterns that could lead to code injection
|
||||
static const List<String> _dangerousPatterns = [
|
||||
r'eval\s*\(',
|
||||
r'Function\s*\(',
|
||||
r'constructor\s*\[',
|
||||
r'__proto__',
|
||||
];
|
||||
|
||||
/// Validates user script for basic security checks
|
||||
/// Returns null if valid, error message if invalid
|
||||
String? _validateScript(String script) {
|
||||
// Check script length to prevent DoS
|
||||
if (script.length > _maxScriptLength) {
|
||||
return 'Script exceeds maximum length of $_maxScriptLength characters';
|
||||
}
|
||||
|
||||
// Check for dangerous patterns
|
||||
for (final pattern in _dangerousPatterns) {
|
||||
final regex = RegExp(pattern, caseSensitive: false);
|
||||
if (regex.hasMatch(script)) {
|
||||
return 'Script contains potentially dangerous pattern: ${pattern.replaceAll(r'\s*\(', '(').replaceAll(r'\s*\[', '[')}';
|
||||
}
|
||||
}
|
||||
|
||||
return null; // Script is valid
|
||||
}
|
||||
|
||||
void _initialize() {
|
||||
if (state.initialized) return;
|
||||
_runtime = getJavascriptRuntime();
|
||||
@@ -100,7 +130,26 @@ class JsRuntimeNotifier extends StateNotifier<JsRuntimeState> {
|
||||
}
|
||||
|
||||
final httpRequest = currentRequestModel.httpRequestModel;
|
||||
final userScript = currentRequestModel.preRequestScript;
|
||||
final userScript = currentRequestModel.preRequestScript!;
|
||||
|
||||
// Security: Validate user script before execution
|
||||
final validationError = _validateScript(userScript);
|
||||
if (validationError != null) {
|
||||
final term = ref.read(terminalStateProvider.notifier);
|
||||
term.logJs(
|
||||
level: 'error',
|
||||
args: ['Script validation failed', validationError],
|
||||
context: 'preRequest',
|
||||
contextRequestId: requestId,
|
||||
);
|
||||
state = state.copyWith(lastError: validationError);
|
||||
// Return original request without executing the script
|
||||
return (
|
||||
updatedRequest: httpRequest!,
|
||||
updatedEnvironment: activeEnvironment,
|
||||
);
|
||||
}
|
||||
|
||||
final requestJson = jsonEncode(httpRequest?.toJson());
|
||||
final environmentJson = jsonEncode(activeEnvironment);
|
||||
final dataInjection = '''
|
||||
@@ -190,7 +239,26 @@ class JsRuntimeNotifier extends StateNotifier<JsRuntimeState> {
|
||||
|
||||
final httpRequest = currentRequestModel.httpRequestModel; // for future use
|
||||
final httpResponse = currentRequestModel.httpResponseModel;
|
||||
final userScript = currentRequestModel.postRequestScript;
|
||||
final userScript = currentRequestModel.postRequestScript!;
|
||||
|
||||
// Security: Validate user script before execution
|
||||
final validationError = _validateScript(userScript);
|
||||
if (validationError != null) {
|
||||
final term = ref.read(terminalStateProvider.notifier);
|
||||
term.logJs(
|
||||
level: 'error',
|
||||
args: ['Script validation failed', validationError],
|
||||
context: 'postResponse',
|
||||
contextRequestId: requestId,
|
||||
);
|
||||
state = state.copyWith(lastError: validationError);
|
||||
// Return original response without executing the script
|
||||
return (
|
||||
updatedResponse: httpResponse!,
|
||||
updatedEnvironment: activeEnvironment,
|
||||
);
|
||||
}
|
||||
|
||||
final requestJson = jsonEncode(httpRequest?.toJson());
|
||||
final responseJson = jsonEncode(httpResponse?.toJson());
|
||||
final environmentJson = jsonEncode(activeEnvironment);
|
||||
|
||||
@@ -56,7 +56,7 @@ Future<bool> openHiveBoxes() async {
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
debugPrint("ERROR OPEN HIVE BOXES: $e");
|
||||
// Error opening Hive boxes - logging suppressed for security
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ Future<void> clearHiveBoxes() async {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("ERROR CLEAR HIVE BOXES: $e");
|
||||
// Error clearing Hive boxes - logging suppressed for security
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ Future<void> deleteHiveBoxes() async {
|
||||
}
|
||||
await Hive.close();
|
||||
} catch (e) {
|
||||
debugPrint("ERROR DELETE HIVE BOXES: $e");
|
||||
// Error deleting Hive boxes - logging suppressed for security
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ class HiveHandler {
|
||||
late final LazyBox dashBotBox;
|
||||
|
||||
HiveHandler() {
|
||||
debugPrint("Trying to open Hive boxes");
|
||||
// Initialize Hive boxes
|
||||
dataBox = Hive.box(kDataBox);
|
||||
environmentBox = Hive.box(kEnvironmentBox);
|
||||
historyMetaBox = Hive.box(kHistoryMetaBox);
|
||||
|
||||
@@ -221,8 +221,6 @@ Future<HttpRequestModel> handleAuth(
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint(res.$1.credentials.accessToken);
|
||||
|
||||
// Add the access token to the request headers
|
||||
updatedHeaders.add(
|
||||
NameValueModel(
|
||||
@@ -238,7 +236,6 @@ Future<HttpRequestModel> handleAuth(
|
||||
oauth2Model: oauth2,
|
||||
credentialsFile: credentialsFile,
|
||||
);
|
||||
debugPrint(client.credentials.accessToken);
|
||||
|
||||
// Add the access token to the request headers
|
||||
updatedHeaders.add(
|
||||
@@ -250,12 +247,10 @@ Future<HttpRequestModel> handleAuth(
|
||||
updatedHeaderEnabledList.add(true);
|
||||
break;
|
||||
case OAuth2GrantType.resourceOwnerPassword:
|
||||
debugPrint("==Resource Owner Password==");
|
||||
final client = await oAuth2ResourceOwnerPasswordGrantHandler(
|
||||
oauth2Model: oauth2,
|
||||
credentialsFile: credentialsFile,
|
||||
);
|
||||
debugPrint(client.credentials.accessToken);
|
||||
|
||||
// Add the access token to the request headers
|
||||
updatedHeaders.add(
|
||||
|
||||
@@ -31,6 +31,7 @@ dependencies:
|
||||
flutter_markdown: ^0.7.6+2
|
||||
flutter_portal: ^1.1.4
|
||||
flutter_riverpod: ^2.5.1
|
||||
flutter_secure_storage: ^9.0.0
|
||||
flutter_svg: ^2.0.17
|
||||
fvp: ^0.32.1
|
||||
highlight: ^0.7.0
|
||||
@@ -47,6 +48,7 @@ dependencies:
|
||||
just_audio: ^0.9.46
|
||||
just_audio_mpv: ^0.1.7
|
||||
just_audio_windows: ^0.2.0
|
||||
logging: ^1.2.0
|
||||
lottie: ^3.3.1
|
||||
markdown: ^7.3.0
|
||||
mime_dart: ^3.0.0
|
||||
|
||||
Reference in New Issue
Block a user