|
| 1 | +import 'package:flutter_test/flutter_test.dart'; |
| 2 | +import 'package:querya_desktop/core/security/archive_path_guard.dart'; |
| 3 | + |
| 4 | +void main() { |
| 5 | + group('isArchiveExtractPathWithinRoot', () { |
| 6 | + test('allows paths inside root', () { |
| 7 | + expect( |
| 8 | + isArchiveExtractPathWithinRoot('/tmp/ext', '/tmp/ext/file.txt'), |
| 9 | + isTrue, |
| 10 | + ); |
| 11 | + }); |
| 12 | + |
| 13 | + test('allows root path itself', () { |
| 14 | + expect( |
| 15 | + isArchiveExtractPathWithinRoot('/tmp/ext', '/tmp/ext'), |
| 16 | + isTrue, |
| 17 | + ); |
| 18 | + }); |
| 19 | + |
| 20 | + test('rejects sibling prefix paths (startsWith false positive)', () { |
| 21 | + expect( |
| 22 | + isArchiveExtractPathWithinRoot('/tmp/abc', '/tmp/abcd/evil.txt'), |
| 23 | + isFalse, |
| 24 | + ); |
| 25 | + }); |
| 26 | + |
| 27 | + test('rejects paths outside root', () { |
| 28 | + expect( |
| 29 | + isArchiveExtractPathWithinRoot('/tmp/ext', '/tmp/other/file.txt'), |
| 30 | + isFalse, |
| 31 | + ); |
| 32 | + }); |
| 33 | + }); |
| 34 | + |
| 35 | + group('isArchiveEntryNameSafe', () { |
| 36 | + test('rejects traversal and absolute names', () { |
| 37 | + expect(isArchiveEntryNameSafe('../evil.txt'), isFalse); |
| 38 | + expect(isArchiveEntryNameSafe('/etc/passwd'), isFalse); |
| 39 | + expect(isArchiveEntryNameSafe(r'\windows\system32'), isFalse); |
| 40 | + }); |
| 41 | + |
| 42 | + test('allows relative safe names', () { |
| 43 | + expect(isArchiveEntryNameSafe('manifest.json'), isTrue); |
| 44 | + expect(isArchiveEntryNameSafe('bin/driver'), isTrue); |
| 45 | + }); |
| 46 | + }); |
| 47 | +} |
0 commit comments