Summary
Five independent layers were audited. If any one layer were wrong, the others would still catch a violation.
| # | Layer | Result |
|---|---|---|
| 1 | Static import analysis | Zero network DLLs, zero network functions imported |
| 2 | Source code audit | No network code, no dynamic library loading, no process spawning |
| 3 | Embedded strings scan | No telemetry endpoints; every URL is inert documentation text |
| 4 | Third-party telemetry | Found and neutralized: ML runtime telemetry disabled at startup |
| 5 | Runtime observation | 0 TCP connections, 0 UDP endpoints while running |
One structural fact frames all five: LocalParrot has no backend. No account system, no license server, no update pinger, no crash reporter. A server that does not exist cannot receive your data.
Layer 1: no network capability is linked
A Windows program reaches the network through a small set of system DLLs (ws2_32, winhttp, wininet,urlmon, dnsapi). LocalParrot imports none of them. Its complete dependency list:
> dumpbin /dependents LocalParrot.exe
ADVAPI32.dll COMCTL32.dll GDI32.dll KERNEL32.dll
SETUPAPI.dll SHELL32.dll USER32.dll dbghelp.dll
dxgi.dll gdiplus.dll ole32.dll
api-ms-win-core-path-l1-1-0.dll
> dumpbin /imports LocalParrot.exe
| findstr /i "ws2_32 winhttp wininet urlmon dnsapi WSA socket"
(no output)All dependencies are local OS facilities: UI, audio, graphics. The app cannot open a socket or an HTTP request through any conventional Windows path because the entry points are not linked.
Layer 2: no hidden path in the code
Static imports could in theory be bypassed by loading a DLL at runtime. The application source contains:
- Zero calls to
LoadLibrary/GetProcAddress: the app never loads a library dynamically, so it cannot acquire network functions at runtime. - Zero calls to
CreateProcess/WinExec/system: it never spawns another process, so it cannot delegate networking to a helper. - One
ShellExecuteW, which opens your localdictionary.jsonfrom Settings. It never receives a URL. - Audio, transcription and typed text live only in process memory. Recorded audio is never written to disk.
Layer 3: embedded strings, no telemetry endpoints
A full ASCII and UTF-16 string extraction of the 20 MB binary (which statically links the speech and language runtimes) was scanned for URLs and known analytics hosts (Sentry, Mixpanel, Amplitude, Segment, Google Analytics, AWS, Azure, plus generic telemetry markers). The only URLs present are documentation citations baked into the open-source ML libraries: arxiv papers, GitHub source references, links inside error messages. With no network code in the binary (layers 1 and 2), a URL string is inert text. No analytics endpoint appears at all.
Layer 4: the one real finding, and its fix
Honesty requires reporting what we found. onnxruntime, the inference engine inside the speech stack, compiles in a Windows ETW trace provider (Microsoft.ML.ONNXRuntime). Two facts about it:
- ETW is a local Windows tracing facility, not a network channel. The app still opens zero connections. The only way such events could leave the machine is Windows "optional diagnostic data", in which case Windows itself forwards runtime metadata (versions, errors), never audio or text.
- LocalParrot disables it at the source anyway. At startup, before any model or inference session exists, the app creates the runtime environment and calls the official
DisableTelemetryEventsAPI on it, holding that state for the lifetime of the process.
Verification, from the startup log of the audited build:
[INFO] LocalParrot starting
[INFO] ORT telemetry disabled (onnxruntime 1.24.4)
[INFO] VAD: Silero engine selected
[INFO] ASR: Parakeet engine selectedThe disable line appears before either inference engine initializes: no session ever runs with telemetry active.
Layer 5: watched at runtime, zero connections
With the app fully initialized (models loaded, hotkey armed), the process was inspected for network endpoints:
> $lp = (Get-Process LocalParrot).Id
> Get-NetTCPConnection -OwningProcess $lp
> Get-NetUDPEndpoint -OwningProcess $lp
TCP endpoints : 0
UDP endpoints : 0Or simply watch Resource Monitor's Network tab while you dictate: LocalParrot never appears.
What is actually distributed
The installer ships exactly one executable, plus model weight files (.onnx, .gguf: data, not code) and license texts. There is no updater, no background service, no scheduled task, no helper process.
Verify it yourself
- The 60-second test: turn on airplane mode and dictate. Recognition, punctuation and AI cleanup all keep working. Cloud dictation stops the moment the network disappears; LocalParrot does not notice.
- The firewall test: add a Windows Firewall rule blocking all outbound traffic for
LocalParrot.exe. Nothing changes, ever, because nothing was trying to get out. - The one-liner: with LocalParrot running, paste this read-only query into PowerShell. It lists every network connection owned by the process. It lists none, because there are none.
> Get-NetTCPConnection -OwningProcess (Get-Process LocalParrot).Id
(no connections)
> Get-NetUDPEndpoint -OwningProcess (Get-Process LocalParrot).Id
(no endpoints)A deliberate choice: we do not ask you to download and run a verification script. Downloading and executing scripts from websites is precisely the habit a privacy product should not encourage. Every check on this page is either a built-in Windows feature or a single line you can read in full before pressing Enter.
Scope and honesty notes
- This is a first-party audit by Krila Software, performed with standard Windows tooling (MSVC dumpbin, string extraction, PowerShell network queries, source review). The methodology is published precisely so third parties can repeat every check against the shipped binary.
- Windows itself performs its own network activity (SmartScreen checks on downloaded installers, DNS, updates). That traffic belongs to the OS, exists with or without LocalParrot, and is outside any application's control.
- Data handling in one sentence: dictation audio lives only in RAM during a dictation and is discarded after transcription; text goes only to the app you are typing into; settings and your personal dictionary are local JSON files under
%APPDATA%\LocalParrot.
Found something we missed? We want to know: [email protected]