Security-Fixes aus dem flutter-security Audit

CRIT:
- Cloud-Token jetzt in flutter_secure_storage (Keystore/Keychain) statt SharedPreferences, mit Migration alter Eintraege
- usesCleartextTraffic entfernt (kein HTTP-Klartext mehr)
HIGH:
- Path-Traversal gefixt: p.basename bei YouTube-Download, Navidrome-Download und Cloud-Auto-Sync
MED:
- allowBackup=false (kein Backup von Token-Daten)
- Navidrome-Salt kryptographisch sicher (Random.secure statt Timestamp)
This commit is contained in:
Hermes (Server)
2026-08-01 13:10:18 +02:00
parent 8b6a04ead8
commit 77a20422be
5 changed files with 45 additions and 17 deletions
+6 -2
View File
@@ -1,8 +1,10 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:crypto/crypto.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../models/song.dart';
@@ -81,7 +83,9 @@ class NavidromeService {
_serverUrl = url.endsWith('/') ? url.substring(0, url.length - 1) : url;
_user = user;
_password = password;
_salt = DateTime.now().millisecondsSinceEpoch.toString();
// Kryptographisch sicherer Salt (vorher millisecondsSinceEpoch = vorhersagbar)
final rng = Random.secure();
_salt = base64Encode(List.generate(16, (_) => rng.nextInt(256)));
_token = md5.convert(utf8.encode(_password + _salt)).toString();
}
@@ -180,7 +184,7 @@ class NavidromeService {
final musikDir = Directory('${dir.path}/music');
if (!await musikDir.exists()) await musikDir.create(recursive: true);
final safeName = s.titel.replaceAll(RegExp(r'[^\w\s-]'), '').trim();
final safeName = p.basename(s.titel).replaceAll(RegExp(r'[^\w\s-]'), '').trim();
final kurzId = s.id.length > 8 ? s.id.substring(0, 8) : s.id;
final dateiName = '${safeName.isEmpty ? "song" : safeName}_$kurzId.mp3';
final dateiPfad = '${musikDir.path}/$dateiName';