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:
copilot-swe-agent[bot]
2025-10-11 18:57:30 +00:00
parent f119168f87
commit 5c117fe82f
4 changed files with 76 additions and 11 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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(

View File

@@ -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