FireAIs säkerhetsblogg

Av FireAI Security & Research Team · Publicerad

Kör en lokal LLM på Apple Silicon för säkerhetstriage

Kör en lokal LLM på Apple Silicon för säkerhetstriage

En modell som klassar en nätverksanslutning som värd att titta på eller inte, som körs på samma Mac som gjorde anslutningen, ändrar tre saker på en gång: vad som lämnar maskinen, vad det kostar att köra och om det fortsätter att fungera när nätverket i sig är det som är misstänkt. Alla tre har större betydelse för ett säkerhetsverktyg än för de flesta andra användningar av en språkmodell, varför den här artikeln specifikt handlar om fallet på enheten snarare än att anropa ett API.

Varför på enheten, speciellt för triage

Att skicka en anslutningslogglinje till en molnmodell för klassificering innebär att för varje enskilt beslut överföra vilken app på din Mac som pratar med vilken värd, på vilken port just nu. Inget av det är en hemlighet i hur ett lösenord är, men det är precis den typen av metadata som en säkerhetsmedveten installation försöker minimera delning, och ett verktyg vars hela syfte är att bestämma vad din Mac får skicka någon annanstans har en uppenbar anledning att inte själv vara beroende av att skicka något någon annanstans för varje beslut den fattar. Att köra modellen lokalt tar bort det beroendet helt: logglinjen lämnar aldrig enheten, eftersom det inte finns något nätverksanrop i beslutsvägen alls.

Det andra skälet är kontinuitet. Ett molnbaserat triagesteg är bara lika tillgängligt som din internetanslutning och leverantörens API, som båda är exakt de saker som kan försämras eller avsiktligt skäras under en verklig incident. En modell som körs i lokalt minne fortsätter att svara med nätverket nere, Wi-Fi avstängt eller en misstänkt kompromiss pågår på samma länk som API-anropet skulle ha använt.

MLX: Apples eget array-ramverk

MLX är ett array-ramverk byggt av Apples forskargrupp för maskininlärning specifikt för Apples kisel, med Python, C++, C och Swift API. Dess egen dokumentation beskriver en enhetlig minnesmodell som dess definierande designval: arrayer i MLX lever i delat minne, och operationer på dem kan köras på vilken enhet som helst – CPU eller GPU – utan att modellens vikter kopieras mellan separata minnespooler först. Det spelar en konkret roll för en bärbar dator: en diskret GPU-maskin måste kopiera en modells vikter över en buss till GPU-minnet innan den kan beräkna någonting, vilket kostar tid och fördubblar minnesfotavtrycket; på en Macs enhetliga minnesarkitektur delar CPU och GPU redan samma fysiska minne, så det finns inget att kopiera.

mlx-lm, det kompletterande paketet för att köra språkmodeller på MLX, installeras med ett enda kommando och levererar en standardmodell ur kartongen:

MLX-inställning
pip install mlx-lm
# runs the default model (mlx-community/Llama-3.2-3B-Instruct-4bit)
mlx_lm.generate --prompt "How tall is Mt Everest?"
# or name a specific quantized model from the mlx-community hub
mlx_lm.generate --model mlx-community/Mistral-7B-Instruct-v0.3-4bit --prompt "..."
# interactive chat session instead of a single prompt
mlx_lm.chat
# convert and quantize a model yourself
mlx_lm.convert --model mistralai/Mistral-7B-Instruct-v0.3 -q

llama.cpp: det bärbara alternativet

llama.cpp är den äldre, mer allmänt porterade av de två, skriven i C/C++ utan att Python-körning krävs vid slutledningstidpunkten. Dess egen README anger projektets ställning till denna hårdvara direkt: Apples kisel behandlas som, med projektets ord, "en förstklassig medborgare - optimerad via ARM NEON, Accelerate och Metal-ramverk," och dess byggdokumentation bekräftar att på macOS är Metal GPU-backend aktiverad som standard, med en byggtidsflagga för att specifikt inaktivera den i CPU.

llama.cpp bygga och köra
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build
cmake --build build --config Release
# Metal is on by default on macOS; add -DGGML_METAL=OFF to the first
# command above if you need to force CPU-only inference
llama cli -hf ggml-org/Qwen3.5-0.8B-GGUF
# or run it as a local server instead of a one-shot command
llama serve -hf ggml-org/Qwen3.5-0.8B-GGUF

llama.cpp fungerar från GGUF-filer, ett modellformat med en enda fil som samlar de kvantiserade vikterna och allt som behövs för att köra dem; kommandot ovan drar en direkt från ett Hugging Face-förråd med namn. MLX, däremot, håller sig närmare ett inbyggt Python-arbetsflöde, konverterar och kvantifierar modeller till sitt eget format i förväg. Ingetdera är strängt taget bättre: llama.cpp är den du ska nå om du vill ha en enda kompilerad binärfil utan Python-beroende, MLX är den du ska nå om du redan bygger resten av din pipeline i Python och vill ha förstklassig tillgång till Apples enhetliga minnesmodell därifrån.

Kvantisering: vad du faktiskt byter mot en mindre modell

Kvantisering lagrar varje modellvikt i färre bitar än de 16 eller 32 som modellen tränades i, vilket krymper både filen på disken och minnet som behövs för att köra den, till en viss kostnad för utskriftskvaliteten. llama.cpps egen kvantiseringsdokumentation listar exakta siffror för bitar per vikt för varje schema som det stöder, vilket är ett mer exakt sätt att resonera kring avvägningen än den vanliga förkortningen "4-bitars" eller "8-bitars":

Från llama.cpps dokumentation för kvantiseringsverktyg.
Schema familjExempel schemanBitar per vikt
Full precision (referens)F1616,0
Nästan förlustfriF8_08,50
Mellanklass av högre kvalitetQ5_K_S / Q5_K_M5,57 - 5,70
Balanserad kvalitet och storlekQ4_K_S / Q4_K_M4,67 - 4,89
Mindre, mer förlustQ3_K_S / Q3_K_M / Q3_K_L3.64 - 4.30
Extrem kompressionIQ2_XXS ... IQ2_M2,00 - 2,93

Att multiplicera en modells parameterantal med dess bitar per vikt ger en grov minnesuppskattning för vikterna enbart: en modell med 7 miljarder parametrar vid Q4_K_M:s 4,89 bitar per vikt behöver ungefär 7 000 000 000 × 4,89 ÷ 8 byte, eller ungefär 43 aktiveringar för fönstret, innan man lägger till fler media för fönstret. topp beroende på hur mycket text du matar in den. Det är en beräkning från den citerade bitar-per-vikt-siffran, inte en siffra som antingen projekt publicerar direkt, och den faktiska minnesanvändningen kommer att bli högre när en riktig prompt och dess sammanhang har laddats. Den praktiska vägledningen som följer av tabellen är enkel: för en uppgift som att klassificera en anslutningslogglinje åt gången, där ingången är kort och den nödvändiga utmatningen är en liten strukturerad bedömning, är en Q4_K_M-klassmodell mycket ofta rätt handel — märkbart mindre och snabbare än Q8_0 eller F16, utan att sjunka till extremkompressionsnivån där utdatakvaliteten försämras kraftigt.

Inget av projekten publicerar något minneskrav per Mac-konfiguration, så det praktiska tillvägagångssättet är att arbeta bakåt från uppskattningen ovan och lämna verkligt utrymme: själva macOS, din webbläsare och allt annat som körs behöver också enhetligt minne, och en modell som knappt passar med inget annat öppet kommer att byta eller stanna så fort du byter till en annan app. På en Mac med en blygsam mängd enhetligt minne, argumenterar det för att hålla sig i den mindre delen av tabellen ovan – några miljarder parametrar vid Q4_K_M snarare än en mycket större modell med samma kvantisering – och att reservera de större alternativen med högre precision för maskiner med minne över. För en snäv klassificeringsuppgift som den här artikeln handlar om, tenderar en mindre modell som ställs en exakt fråga att vara både snabbare och i praktiken mer konsekvent än en större modell med en vag.

Båda projekten är under aktiv utveckling, och den ärliga jämförelsen är mindre "vilket är bättre" än "som passar din pipeline." llama.cpp kompileras till en enda binär fil utan att Python-körtid krävs vid slutledningstidpunkten, vilket spelar roll om du vill bädda in det i en annan mjukvara utan att skicka en Python-tolkare vid sidan av den. MLX förutsätter att du redan arbetar i Python (eller Swift, för vilken den också skickar bindningar) och belönar det med stramare integration i Apples egen maskininlärningsstack och den enhetliga minnesmodellen som beskrivs ovan. Ett säkerhetsverktyg byggt som en fristående macOS-applikation, vilket är den situation som FireAI själv befinner sig i, sitter närmare llama.cpp-änden av det spektrumet; en forskningsanteckningsbok som utforskar vilket promptmönster som fungerar bäst sitter närmare MLX-änden.

Ett promptmönster för triaging av en anslutning

Ju snävare fråga du ställer en liten lokal modell, desto mer tillförlitligt svarar den. För en enskild anslutning innebär det att ge den exakt de fält som en mänsklig recensent skulle titta på - inget mer, inget antydt - och att be om en strukturerad dom snarare än en fri formsprosa:

triage-promptmall (illustrerande, inte testad mot någon datauppsättning)
System: You review one outbound network connection at a time. You are
given only the fields listed below. Do not assume anything not stated.
Respond with exactly two lines: a verdict (allow, ask, or block) and a
one-sentence reason a non-expert could understand.

Connection:
  app: UpdaterHelper.app
  code_signature: unsigned
  destination: 91.203.xxx.xxx:4444
  protocol: TCP
  threat_feed_hit: none
  first_seen: yes (no prior rule for this app)

Verdict:

Fälten som är viktiga är de som en kodsigneringskontroll och ett hotflöde faktiskt kan producera utan att gissa: om binären är signerad och av vem, var den försöker ansluta och på vilken port, om den destinationen dyker upp på ett hotflöde och om det här är första gången den här appen har försökt ansluta överhuvudtaget. Att be om en fast tvåradsutgång, snarare än en öppen förklaring, gör resultatet lättare att logga, lättare att jämföra över tusentals anslutningar och mycket svårare för modellen att fylla med säkringsspråk som låter auktoritativt utan att säga något som kan kontrolleras.

En liten modell kommer ibland att ignorera det begärda formatet ändå - tre rader istället för två, en extra varning, ett domord som inte är ett av de tre du bad om. Behandla det som ett ingenjörsproblem, inte ett modelleringsproblem: validera resultatet mot den exakta form du förväntar dig, och om det inte stämmer överens, fråga antingen om eller fall tillbaka till den säkraste domen (fråga, vilket betyder visa en människa) istället för att försöka analysera ett lösare svar. Ett triagesteg som misslyckas på ett säkert sätt på felaktig utdata är mycket mer användbart än ett som då och då producerar en självsäker men omöjlig linje och tyst släpper den.

Kör det här mönstret över en hel dag av anslutningsförsök snarare än ett i taget och formen på arbetsbelastningen ändras: de flesta anslutningar kommer från appar med en befintlig regel och når aldrig modellen alls, ett mindre antal ses verkligen först och får en dom, och bara en bråkdel av dessa domar är något annat än en rutin tillåter. Modellens verkliga jobb, vid den tidpunkten, är inte att vara en säkerhetsexpert; det är att klippa en lång lista av först-sedda kopplingar ner till den lilla delmängd en person faktiskt behöver titta på, vilket är ett mycket mer uppnåeligt mål för en modell med några miljarder parametrar än en öppen säkerhetsbedömning skulle vara.

Där detta går fel

  • En liten lokal modell kan ge en säker, välskriven, helt felaktig anledning. Inget med att springa lokalt förändrar den risken; det förändras bara där misstaget inträffar, inte om det kan hända.
  • Kontextfönster är ändliga och en lång, bullrig logg får inte plats. Att sammanfatta eller förfiltrera innan modellen ser data introducerar sin egen felpunkt - du kan förlora den enda raden som betydde något innan modellen någonsin får en chans att titta på den.
  • Modellen ser bara vad loggraden innehåller. Den kan inte se inuti krypterad trafik, den kan inte verifiera att ett hotflöde är aktuellt och det kan inte veta din avsikt – en anslutning från ett verktyg som du precis installerat med avsikt ser identisk ut med en från ett verktyg du aldrig har hört talas om.
  • En dom är inte en handling. Ingenting här ska blockera, ta bort eller tyst tillåta en anslutning på egen hand; en person behöver fortfarande se orsaken och bekräfta den, och kunna vända samtalet om modellen hade fel.

Den sista punkten är inte en begränsning som är specifik för en liten kvantifierad modell som körs på en bärbar dator - det gäller för varje automatiserat säkerhetsbeslut, lokalt eller moln, liten modell eller stor. Värdet av att köra det lokalt är vad det tar bort från ekvationen (ett nätverksberoende, en återkommande räkning, en tredje part som tar emot din anslutningsmetadata), inte ett påstående om att det tar bort behovet av en människa i slingan.

Där FireAI passar detta mönster

FireAI, HisnLabs brandvägg för Mac, levererar något byggt på samma idé, i en snävare omfattning än en allmän chattmodell: en valfri lokal modell, en extra nedladdning på ungefär 1,5 GB, som körs helt på Mac och granskar anslutningar från appar som ännu inte har någon regel. Det kräver macOS 14 eller senare på Apple silicon, tillämpar offentliga hotflöden lokalt snarare än att kontrollera dem mot en fjärrtjänst, och visar orsaken till sitt beslut i samma tillståndsprompt som den använder för att be dig att tillåta eller neka anslutningen – vart och ett av dessa beslut blir en synlig, redigerbar regel, och vilken som helst av dem kan ångras. Det är värt att vara exakt om vad det är och inte är: det är inte den öppna chattmodellen med få miljarder parametrar som den här artikeln har beskrivit, och det är inte ett antivirus eller en VPN – den gör ett snävt klassificeringsjobb lokalt och lämnar det sista samtalet till den som läser uppmaningen.

Var FireAI och HisnLabs kommer in

FireAI’s own connection reviewer is this exact bet, made narrower still: an optional, roughly 1.5 GB on-device model, macOS 14 and up, Apple silicon only, reviewing one thing (should this unknown app reach this destination) with a visible reason and an undo button — and, like the triage pattern in this article, it still needs a person to confirm anything consequential.

FireAI är HisnLabs eget verktyg: en AI-brandvägg som körs direkt på din Mac. Den visar varje anslutning dina appar gör, på klarspråk, och låter dig avgöra vad som lämnar din Mac — AI:n körs lokalt, så din trafik skickas aldrig till oss eller någon annan. HisnLabs säkerhetsforskningsteam är de som håller de bedömningarna tillförlitliga: de katalogiserar vilka domäner som är vanlig telemetri och vilka som är en riktig tjänst, spårar land och nätverk bakom en anslutning och tränar den lokala modellen (Autopilot-funktionen) på verkliga trafikmönster — utan att något av det lämnar din Mac.

Du kan läsa om de tekniska besluten bakom, eller prova FireAI i 17 dagar, på FireAI, från HisnLabs.

Källor