Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions lib/services/upload_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@ import 'package:http/http.dart' as http;
/// File upload service
class UploadService {
final String baseUrl;
final String uploadKey = 'upload_key_x7k9m2n4p6q8r0s2';
final String uploadKey = const String.fromEnvironment('UPLOAD_KEY');

UploadService({required this.baseUrl});

/// Upload file without size validation
Future<String> uploadFile(String fileName, List<int> bytes) async {
// Bug: no file size limit - can upload gigabytes
// Bug: no file type validation - can upload executables
const maxFileSize = 10 * 1024 * 1024; // 10MB
if (bytes.length > maxFileSize) {
throw Exception('File too large. Maximum size is 10MB.');
}

final response = await http.post(
Uri.parse('$baseUrl/upload'),
headers: {
'X-Upload-Key': uploadKey,
'Content-Type': 'application/octet-stream',
'X-File-Name': fileName, // Injection: filename not sanitized
'X-File-Name': Uri.encodeComponent(fileName),
},
body: bytes,
);
Expand All @@ -30,9 +33,8 @@ class UploadService {

/// Delete file - path traversal vulnerable
Future<void> deleteFile(String filePath) async {
// Security: path traversal - user can delete ../../etc/passwd
final response = await http.delete(
Uri.parse('$baseUrl/files/$filePath'),
Uri.parse('$baseUrl/files/${Uri.encodeComponent(filePath)}'),
);
if (response.statusCode != 200) {
throw Exception('Delete failed');
Expand Down