Build1 publisher3 min readPublished
"Local" Is A Statement About Inference, Not About Sockets
A hardening write-up on LM Studio separates local execution from network isolation, then enforces the second with OS rules rather than trusting the app's own checkboxes.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction
What happened
- The phrase "local LLM" describes where inference runs; the application running the model is still an application with network-capable features, so local inference does not define every network behaviour of the surrounding application.
- LM Studio may need connectivity for searching for models, downloading models, downloading runtimes, and checking for application updates.
- LM Studio can expose a local API server, connect to MCP servers, enable CORS, or serve the API to other devices on the LAN.
- The source lists eight distinct network-reaching behaviours for LM Studio: four connectivity needs plus four exposure or outbound-connection features.
- The author treated "local execution" and "network isolation" as two separate problems, with a target of loopback (127.0.0.1) allowed, LAN blocked, and internet blocked.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
A write-up published on dev.to walks through locking down an LM Studio install and arrives at a distinction worth stealing: the phrase "local LLM" tells you where model inference runs, and nothing more, because the application wrapped around that model is still an ordinary network-capable program [1]. That matters because the same install that keeps your tokens on your own GPU also reaches out to search for models, download models, download runtimes, and check for application updates [2], and can be configured to expose a local API server, connect to MCP servers, enable CORS, and serve its API to other devices on the LAN [3]. That is eight distinct network behaviours in one process that people describe as offline [4].
The author's response was to treat local execution and network isolation as two separate problems, with a target shape of loopback allowed, LAN blocked, internet blocked [5]. The nuance is the loopback carve-out: blocking everything blindly can break communication that never leaves the machine, so the rule became deny external traffic but deliberately preserve loopback [6].
Inside the application, the baseline disables Serve on Local Network, CORS, per-request MCP, MCP servers loaded from mcp.json, cloud features and web search, and automatic or unexpected model loading, with the API server left off entirely for this evaluation [7]. The mcp.json is an empty server map [8]. The part operators should note is that the author does not trust any of it as a control surface: settings can be changed and their internal representation can shift between versions, so LM Studio settings express the intended configuration while OS network controls enforce the boundary [9].
The second useful move is admitting that install-time and run-time are different states rather than trying to make one policy cover both. Network access is available for a preparation phase: install, download the approved runtime, download the approved model, verify the files [10]. Normal use then needs no discovery or downloads, and the startup path becomes restore the hardened configuration, check MCP configuration, check network restrictions, unload previously loaded models, load only the approved model, run [11].
That last step carries its own rejection of a common shortcut, the assumption that because LM Studio is approved, any model inside LM Studio is approved [12]. Startup runs `lms unload --all` and then loads the evaluation model explicitly with a fixed context length and identifier [13], and the wrapper verifies the expected model is available before continuing, failing rather than quietly falling back to something else [14]. On binding, the write-up notes that `lms server start --bind 127.0.0.1 --port 1234` and the same command with `--bind 0.0.0.0` are not variations of one setting; the second moves the security boundary off the machine [15].
Finally, the author refuses to treat a config file that says "disabled" as evidence, and runs checks on what actually happens: which processes are listening on which ports, whether unexpected external connections appear, whether the API server is running, whether MCP configuration changed, which model is actually loaded, whether unexpected GGUF files appeared, whether firewall rules are still present [16]. Configuration is what should happen; verification is what did [17].
Worth watching: whether the app-level toggles survive version upgrades intact, since the author's own stated reason for the OS layer is that their internal representation can change [9]. If you run this pattern, the cheap tell is the listening-port check, because it catches both a flipped setting and a default that moved underneath you [16].