<- all posts

Uninstall This App — and the Security Sweep That Followed

// 2026-09-06 · Frederic Haddad · 8 min read

securitylocal-modelsengineering

what happened — one uninstall, three serious findings

It started as the most boring request I have made all year. Uninstall a VPN client from one of the machines I run. Ten seconds of work.

Except the processes kept coming back. I killed them, they respawned. Killed them again, same thing. The application was gone — dragged to the trash, folder deleted, done — and its processes were still starting themselves. Because the app was never the thing keeping them alive. Background service definitions were, small configuration files registered at install time that tell the operating system: if this stops, start it again. Removing the app removed the app. It did not remove the instruction to keep running it.

That is a five-minute fix once you know where to look. But it left me with an uncomfortable question: what else did I install over the last year that quietly registered itself the same way? So instead of finishing the uninstall, I pulled the thread and did a full sweep of what was actually running and what was actually listening on the network.

Three findings, in ascending order of how badly I slept that night.

One. A container-management socket proxy, completely unauthenticated, exposed on the local network. That is not a minor leak. Access to a container-management socket is, for practical purposes, administrative control of the machine — you can start containers, mount the host filesystem into them, and read or write anything. No password. No token. Just reachable.

Two. A local AI model server bound to all network interfaces instead of localhost. The difference is one configuration value and it is the whole ballgame: localhost means only the machine itself can talk to it, all-interfaces means anything on the network can. And it was kept alive by a service definition set to restart it, so killing the process would have accomplished exactly nothing. It would have come back, bound the same way, within seconds.

Three. Two independently-running instances of that same model server. I fixed the first service definition, felt good about myself, and then found the second instance configured somewhere else entirely and still listening. One fix was not the fix.

None of these were malicious. Nobody attacked me. They arrived as side effects of installing AI tooling — package managers, setup scripts, convenience installers that register a background service and never say so in a way you would notice. I chose the tools. I did not choose the exposure. It accumulated.

the part where I was wrong

Here is the bit I would rather leave out.

My first test for whether the model server was reachable from the network was to query it from the same machine it was running on. It answered. I noted it as confirmed and moved on.

That test proves nothing. Of course it answered — every service answers itself, whether it is bound to localhost or to every interface on the box. I had tested the one condition that cannot distinguish between the safe case and the dangerous one. I was wrong, said so, threw the result out, and replaced it with the only thing that actually settles it: pulling the service configuration and reading the bind address it was launched with. Configuration is truth. A response from the machine to itself is theatre.

There was a second correction the same day. I argued for keeping a particular firewall enabled, and the argument I reached for was the standard one — untrusted networks, airport wifi, the coffee shop threat model. Then I got pushed back on, correctly. That is a laptop threat model. The machine in question is a stationary desktop that never leaves a home network. Same conclusion, possibly, but the reasoning was recited rather than reasoned. I conceded it and re-scoped the argument around what that machine actually faces: other devices on the same wifi, guests, and every IoT gadget in the building. A stationary desktop pretending to be a laptop is its own class of mistake — I wrote about that in Your Server Still Thinks It's a Laptop.

Good security advice is specific to your actual threat model. Checklist security tells you to turn the firewall on. Real security tells you what you are turning it on against. If your advisor cannot answer the second question, you are buying ritual.

And one older find worth naming, because it is the reason I take this seriously: a service left running with no authentication, bound to every interface, for over a day. Effectively remote code execution for anyone on that wifi. It was caught by the owner's own instinct, on a hunch. Not by an alarm. Not by monitoring. There was no alarm to go off.

the quarterly audit — five questions to hand your IT person

This is deliberately written so a non-technical owner can forward it and get real answers back. Five items, once a quarter, ninety minutes of someone's time.

1. What is actually listening, right now? Not what we think we installed — an enumeration of every process holding an open network port on every machine that runs AI workloads. Ask for the list. Every line should have a name attached to it, and someone should be able to say why it is there. Anything nobody can explain gets investigated, not ignored.

2. For each one, is it bound to localhost or to all interfaces? This is the single highest-value question on the list. Localhost means the service is reachable only by software on that same machine. All-interfaces means anything on the network can reach it. Most local AI tools default to the second because they assume they are on a trusted developer laptop. That assumption is wrong the moment the machine sits in an office.

3. Which of those require authentication? Ask plainly: if I were on the office wifi with a laptop, could I use this without a password? For model servers, gateways, admin dashboards, and container-management sockets the honest answer is usually no password at all. Anything unauthenticated must be on localhost, behind a real access control, or switched off. No fourth option.

4. What service definitions exist, and who created them? This is the lesson from my uninstall. Killing a process is not removing a service. Get an inventory of every registered background service on those machines and, for each, what installed it. You will find things nobody remembers approving. That is the normal result, not a sign of negligence.

5. What happens when we uninstall something? Pick one tool, remove it properly, then re-run items 1 and 4 and confirm it is genuinely gone. If your removal process leaves service definitions behind, you have been accumulating ghosts for as long as you have been experimenting.

Run those five, write down the answers, and compare against last quarter's. The comparison is where the value is. Drift is the finding.

One thing to internalise before you delegate this: "it's only on our internal network" is not a security boundary. Your internal network contains guest phones, a printer with firmware from 2019, contractors' laptops, smart TVs, and whatever the sales team plugged in last week. It is not a wall. It is a room with the door open. Treating it as a perimeter is how a research tool ends up as administrative control of a machine holding client data.

why this bites harder here

A specific pattern is spreading across Gulf SMEs right now, and I like it: businesses running AI models locally instead of sending data to an American API endpoint — usually for data residency, and the broader trade-off is in Cloud vs. Local Models in 2026. Client confidentiality, regulatory nerves, a board that does not want customer records leaving the country. That instinct is correct. Keeping sensitive data in-building is a real control.

But look at what it actually produces. You have moved from a hardened cloud service run by a security team of hundreds to a workstation in an office, configured by whoever was most enthusiastic, running four or five tools installed from setup scripts over eighteen months. The data residency box is ticked. The machine holding the data is now the least defended thing you own. And the way that exposure accumulates — shipping fast, securing late — is the same story as Shipping Faster Than You Can Secure.

Lean teams make this sharper. There is no security function, no change management, no offboarding checklist. The person who set up the model server is a developer with real work to do, and the tooling defaults actively work against them — designed for a solo laptop, deployed in a shared office. Nobody made a bad decision. Everyone made twelve reasonable small ones.

what I do now

I run a listening-services audit as a standard opening step in every engagement that touches self-hosted AI infrastructure. Not as an upsell, as a precondition — I will not build on a machine when I cannot tell you what is currently reachable on it. It takes an hour or two. It has never once come back clean.

If you are running local models for data-residency reasons and nobody has looked at what those machines expose since they were set up, that is worth a conversation. Send me the output of the first two questions above and I will tell you, free, whether you have a problem. Most of the time it is a fifteen-minute fix.

The bad ones are only bad because nobody looked.

If you want a second pair of eyes on any of this — the listening-services audit above, or the other places AI has quietly expanded your attack surface — that is exactly the kind of thing I cover in a consulting day. Book one or send me an inquiry first if you would rather start with a conversation.