mirror of
https://github.com/stablyai/orca.git
synced 2026-10-21 08:03:33 +00:00
* fix(mobile): detect and repair overriding Windows Firewall Block rules for pairing Firewall inspection now reports an overriding inbound Block rule as blocked instead of false success, the UAC repair removes only conflicting rules for the current Orca executable, TCP pairing port, and Private profile before recreating the scoped allow rule, and the notice re-inspects Windows policy after repair instead of optimistically reporting success. Stale focus-triggered inspections can no longer overwrite a newer result during UAC elevation. Fixes #8371 * fix(mobile): inspect the ActiveStore so GPO firewall rules are visible Without -PolicyStore ActiveStore the NetSecurity queries read only the local persistent store, so a GPO-applied Block rule was invisible and the post-repair re-inspection could report a false success on managed hosts.
197 lines
6.9 KiB
TypeScript
197 lines
6.9 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
getWebSocketPort,
|
|
inspectWindowsMobileFirewall,
|
|
repairWindowsMobileFirewall,
|
|
type WindowsMobileFirewallEnvironment
|
|
} from './windows-mobile-firewall'
|
|
|
|
function environment(
|
|
runPowerShell: WindowsMobileFirewallEnvironment['runPowerShell'],
|
|
overrides: Partial<WindowsMobileFirewallEnvironment> = {}
|
|
): WindowsMobileFirewallEnvironment {
|
|
return {
|
|
platform: 'win32',
|
|
isPackaged: true,
|
|
executablePath: "C:\\Users\\O'Brien\\Orca\\Orca.exe",
|
|
systemRoot: 'C:\\Windows',
|
|
runPowerShell,
|
|
...overrides
|
|
}
|
|
}
|
|
|
|
describe('windows mobile firewall', () => {
|
|
it('inspects the exact executable, port, and selected interface profile', async () => {
|
|
const runPowerShell = vi.fn().mockResolvedValue(
|
|
JSON.stringify({
|
|
matchingRuleScopes: [{ remoteAddresses: ['192.168.0.0/24'] }],
|
|
blockingRuleDetected: false,
|
|
localAddress: '192.168.0.108',
|
|
localPrefixLength: 24,
|
|
privateFirewallEnabled: true,
|
|
networkCategory: 'Private'
|
|
})
|
|
)
|
|
|
|
await expect(
|
|
inspectWindowsMobileFirewall(6768, '192.168.0.108', environment(runPowerShell))
|
|
).resolves.toEqual({
|
|
supported: true,
|
|
port: 6768,
|
|
ruleAllowed: true,
|
|
blockingRuleDetected: false,
|
|
privateFirewallEnabled: true,
|
|
networkCategory: 'private',
|
|
inspectionAvailable: true
|
|
})
|
|
|
|
const script = runPowerShell.mock.calls[0]![0] as string
|
|
// Why: without ActiveStore, GPO-applied Block rules are invisible and the
|
|
// post-repair re-inspection could report a false success on managed hosts.
|
|
expect(script).toContain(
|
|
"Get-NetFirewallApplicationFilter -PolicyStore ActiveStore -Program 'C:\\Users\\O''Brien\\Orca\\Orca.exe'"
|
|
)
|
|
expect(script).toContain('Get-NetFirewallProfile -PolicyStore ActiveStore -Name Private')
|
|
expect(script).toContain("LocalPort | Where-Object { [string]$_ -eq 'Any'")
|
|
expect(script).toContain("[string]$_ -eq '6768'")
|
|
expect(script).toContain("C:\\Users\\O''Brien\\Orca\\Orca.exe")
|
|
expect(script).toContain("$profile -match 'Private'")
|
|
expect(script).toContain("Get-NetIPAddress -IPAddress '192.168.0.108'")
|
|
expect(script).toContain('Get-NetFirewallAddressFilter')
|
|
expect(script).toContain("[string]$rule.Action -eq 'Block'")
|
|
expect(script).toContain('remoteAddresses = @($addressFilter.RemoteAddress')
|
|
expect(script).toContain('$localPrefixLength = [int]$ip.PrefixLength')
|
|
})
|
|
|
|
it('treats an overlapping inbound Block rule as overriding a matching Allow rule', async () => {
|
|
const runPowerShell = vi.fn().mockResolvedValue(
|
|
JSON.stringify({
|
|
matchingRuleScopes: [{ remoteAddresses: ['Any'] }],
|
|
blockingRuleDetected: true,
|
|
localAddress: '192.168.0.108',
|
|
localPrefixLength: 24,
|
|
privateFirewallEnabled: true,
|
|
networkCategory: 'Private'
|
|
})
|
|
)
|
|
|
|
await expect(
|
|
inspectWindowsMobileFirewall(6768, '192.168.0.108', environment(runPowerShell))
|
|
).resolves.toEqual({
|
|
supported: true,
|
|
port: 6768,
|
|
ruleAllowed: false,
|
|
blockingRuleDetected: true,
|
|
privateFirewallEnabled: true,
|
|
networkCategory: 'private',
|
|
inspectionAvailable: true
|
|
})
|
|
})
|
|
|
|
it('does not accept a qualifying rule whose remote-address scope excludes the phone subnet', async () => {
|
|
const runPowerShell = vi.fn().mockResolvedValue(
|
|
JSON.stringify({
|
|
matchingRuleScopes: [{ remoteAddresses: ['192.168.1.0/24'] }],
|
|
localAddress: '192.168.0.108',
|
|
localPrefixLength: 24,
|
|
privateFirewallEnabled: true,
|
|
networkCategory: 'Private'
|
|
})
|
|
)
|
|
|
|
await expect(
|
|
inspectWindowsMobileFirewall(6768, '192.168.0.108', environment(runPowerShell))
|
|
).resolves.toMatchObject({
|
|
supported: true,
|
|
ruleAllowed: false,
|
|
inspectionAvailable: true
|
|
})
|
|
})
|
|
|
|
it('does not support non-Windows or unpackaged development builds', async () => {
|
|
const runPowerShell = vi.fn()
|
|
await expect(
|
|
inspectWindowsMobileFirewall(
|
|
6768,
|
|
undefined,
|
|
environment(runPowerShell, { platform: 'darwin' })
|
|
)
|
|
).resolves.toEqual({ supported: false })
|
|
await expect(
|
|
repairWindowsMobileFirewall(6768, environment(runPowerShell, { isPackaged: false }))
|
|
).resolves.toEqual({ ok: false, reason: 'unsupported' })
|
|
expect(runPowerShell).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('returns an actionable status when inspection is unavailable', async () => {
|
|
await expect(
|
|
inspectWindowsMobileFirewall(
|
|
6768,
|
|
undefined,
|
|
environment(vi.fn().mockRejectedValue(new Error('managed policy')))
|
|
)
|
|
).resolves.toEqual({
|
|
supported: true,
|
|
port: 6768,
|
|
ruleAllowed: false,
|
|
blockingRuleDetected: false,
|
|
privateFirewallEnabled: true,
|
|
networkCategory: 'unknown',
|
|
inspectionAvailable: false
|
|
})
|
|
})
|
|
|
|
it('returns an actionable status for malformed or empty PowerShell output', async () => {
|
|
for (const stdout of ['', 'not json']) {
|
|
await expect(
|
|
inspectWindowsMobileFirewall(
|
|
6768,
|
|
undefined,
|
|
environment(vi.fn().mockResolvedValue(stdout))
|
|
)
|
|
).resolves.toMatchObject({
|
|
supported: true,
|
|
ruleAllowed: false,
|
|
inspectionAvailable: false
|
|
})
|
|
}
|
|
})
|
|
|
|
it('repairs only Orca mobile pairing on private networks after elevation', async () => {
|
|
const runPowerShell = vi.fn().mockResolvedValue('{"launched":true,"exitCode":0}')
|
|
await expect(repairWindowsMobileFirewall(6769, environment(runPowerShell))).resolves.toEqual({
|
|
ok: true
|
|
})
|
|
|
|
const outerScript = runPowerShell.mock.calls[0]![0] as string
|
|
const encoded = outerScript.match(/'-EncodedCommand', '([^']+)'/)?.[1]
|
|
expect(encoded).toBeTruthy()
|
|
const repairScript = Buffer.from(encoded!, 'base64').toString('utf16le')
|
|
expect(repairScript).toContain("-Name 'Orca.MobilePairing'")
|
|
expect(repairScript).toContain(
|
|
"Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Block' }"
|
|
)
|
|
expect(repairScript).toContain('$rule | Remove-NetFirewallRule')
|
|
expect(repairScript).toContain('-Profile Private')
|
|
expect(repairScript).toContain('-Protocol TCP')
|
|
expect(repairScript).toContain('-LocalPort 6769')
|
|
expect(repairScript).toContain("-Program 'C:\\Users\\O''Brien\\Orca\\Orca.exe'")
|
|
expect(repairScript).toContain('-EdgeTraversalPolicy Block')
|
|
})
|
|
|
|
it('distinguishes a cancelled UAC prompt from repair failure', async () => {
|
|
await expect(
|
|
repairWindowsMobileFirewall(
|
|
6768,
|
|
environment(vi.fn().mockResolvedValue('{"launched":false,"nativeErrorCode":1223}'))
|
|
)
|
|
).resolves.toEqual({ ok: false, reason: 'cancelled' })
|
|
})
|
|
|
|
it('extracts only explicit valid websocket ports', () => {
|
|
expect(getWebSocketPort('ws://0.0.0.0:6768')).toBe(6768)
|
|
expect(getWebSocketPort('ws://0.0.0.0')).toBeNull()
|
|
expect(getWebSocketPort('not a url')).toBeNull()
|
|
})
|
|
})
|