fix: harden downloader against path traversal, URL escape, oversized bodies

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 13:11:18 +09:00
parent bfa9c09b28
commit a820e97237
2 changed files with 60 additions and 0 deletions
+13
View File
@@ -70,12 +70,25 @@ class ContentDownloader {
}
Future<bool> _downloadPack(ManifestSeason season) async {
// seasonId becomes a filesystem path segment; only accept safe slugs so a
// hostile manifest can never write outside the cache dir.
if (!RegExp(r'^[a-zA-Z0-9_-]+$').hasMatch(season.seasonId)) return false;
if (season.packUrl.contains('..') ||
season.packUrl.startsWith('/') ||
season.packUrl.contains('://')) {
return false;
}
try {
final res = await _client
.get(Uri.parse('$baseUrl/${season.packUrl}'))
.timeout(const Duration(seconds: 30));
if (res.statusCode != 200) return false;
// Packs are tens of KB; anything huge is a server error or an attack.
if (res.bodyBytes.length > 5 * 1024 * 1024) return false;
// Verify in memory before any file is touched, so a bad pack can
// never leave artifacts on disk.
final digest = sha256.convert(res.bodyBytes).toString();