Skip to content

Commit a1f5f23

Browse files
committed
fix(backup): prevent zip slip path traversal in restore
Backport chen08209#1938 (Xeonacid). canonicalize() each zip entry path and verify it stays inside restoreDirPath; throw if a malicious archive contains '..' segments.
1 parent 4e42926 commit a1f5f23

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

lib/common/task.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,16 @@ Future<MigrationData> _restoreTask(RootIsolateToken token) async {
533533
final dir = Directory(restoreDirPath);
534534
await dir.create(recursive: true);
535535
for (final file in archive.files) {
536-
final outPath = join(restoreDirPath, posix.normalize(file.name));
536+
final outPath = canonicalize(join(restoreDirPath, file.name));
537+
final canonicalRestoreDir = canonicalize(restoreDirPath);
538+
if (!outPath.startsWith('$canonicalRestoreDir${Platform.pathSeparator}') &&
539+
outPath != canonicalRestoreDir) {
540+
throw 'Invalid zip entry: path traversal detected in "${file.name}"';
541+
}
542+
final parent = Directory(dirname(outPath));
543+
if (!await parent.exists()) {
544+
await parent.create(recursive: true);
545+
}
537546
final outputStream = OutputFileStream(outPath);
538547
file.writeContent(outputStream);
539548
await outputStream.close();

0 commit comments

Comments
 (0)