Your own program was handing out your files
What you will learn
- Why the software you wrote yourself is the software you never check
- How to find out what your own computers are offering to the rest of the house
- The one test that tells the truth, and why testing from the same machine does not
I wrote a small program to fetch files for me. A hundred lines, the kind of thing you put together on a Tuesday and forget about. Months later I pointed another computer at it, out of idle curiosity, and asked it for a file it had no business handing over. It handed it over.
No password. No check of any kind. No question. Any device in the house could ask, and it would answer.
The hole itself is ordinary. Holes are ordinary. The uncomfortable part is that I had already checked my router, the thing that guards the edge of my network, and the way I reach my machines from outside. I had never once checked the program I wrote myself, because I trusted the author. I was the author. That trust was doing no work at all.
You check the locks on doors other people installed. The door you hung yourself gets a glance, because you remember hanging it. Remembering is not inspecting.
The second assumption, which is the one that actually matters
Underneath the first mistake was a bigger one. I had been treating my home network as a safe room. Everything inside it is mine, so everything inside it is fine.
A home network is not one trusted space. It holds a television that talks to its maker every day, a thermostat running software from years ago that nobody can update, a visitor's phone, a printer that has had no attention since it came out of the box. Any one of those is a foothold. And from a foothold, your helpful little program is just a helpful little program.
So the lesson is two lessons welded together. Software you wrote is still something the world can reach. And the network it sits on is not a wall. It is a room full of strangers you happen to own.
The fix took fifteen minutes. Finding it took months, because nothing was ever looking. That gap between how long it takes to fix and how long it takes to notice is the whole reason to do an inventory on purpose.
The door you hung yourself gets a glance, because you remember hanging it. Remembering is not inspecting.
This is about checking your own machines. Steps one and two only look at things and change nothing, so they are safe to run out of pure curiosity. None of this is about poking at anyone else's computers.
1. Ask the computer what it is offering, rather than remembering
What this does: asks the operating system which programs are waiting for something to contact them, and which part of the network each one is willing to answer.
Why the second half matters more: a program can be waiting in a way that only this computer can reach, or in a way that anything in the house can reach. That one detail is the whole difference between private and published, and it is a single column in the output.
# Linux and macOS: everything that is waiting, and which program owns it
ss -tulpn
# on older systems
netstat -tulpn
# Windows, in PowerShell
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess
How to read it: one column holds an address. If it is the special address that means this computer and nothing else, only programs on the same machine can reach it. If it is the one that means anywhere, then every phone, television and visitor on your network can reach it.
2. Ask each one for something private, from a different device
What this does: makes a plain request to the program from a second machine, with no password and no credentials of any kind.
Why it has to be a second device: asking from the same computer proves nothing, because a program always trusts itself. This is the step people skip, and it is the only one that tells the truth.
What you are looking for: real content where you expected a refusal. If you get data back without proving who you are, you have found what I found. Write down the name and keep going. Finish the list before you start fixing, or you will never finish the list.
# from ANOTHER machine on your network, never the one running it
curl -i http://<the-machine>:<the-number-it-uses>/
# then ask for whatever that program treats as private
curl -i http://<the-machine>:<the-number-it-uses>/<a-path-it-offers>
3. Decide which of three things each one should be
Almost everything belongs in the first group. Almost nothing belongs in the third. Be honest with yourself about which is which.
- This computer only. Nothing else can reach it, so there is nobody to check a password against. This is the strongest and cheapest answer.
- Reachable, but has to ask who is calling. It genuinely needs to answer other devices, so it needs to demand a secret first.
- Open to anyone. Genuinely public, and genuinely harmless if a stranger reads it. This is rarer than it feels.
4. Make it answer only its own machine, which fixes it outright
What this does: changes the setting that decides which part of the network a program will answer, so it answers only the computer it runs on.
Why this is the best fix: it removes the problem instead of guarding it. Most small convenience programs never talk to anything but their own machine, so nothing is lost. It is usually one line in a settings file.
Then prove it: go back to the second device and ask again. You want to be turned away.
# from the second device, after the change
curl -i --max-time 5 http://<the-machine>:<the-number-it-uses>/
# a refused connection or a timeout is the result you want
If it still answers: something else is passing requests through to it. A front desk program that forwards traffic, or a packaging system that published the program on your behalf, are the two usual culprits.
5. If it really must be reachable, make it demand a secret
What this does: generates a long random secret, and keeps it in a file only you can read rather than inside the program.
Keep this boring: one long shared secret, checked on every single request, stops casual access completely. Casual access is what you are actually facing on a home network.
# something you would never think of yourself
openssl rand -hex 32
# keep it out of the program and out of your command history,
# in a file only you can open
chmod 600 <your-secret-file>
Three rules for using it: turn the request away before doing any work at all; never write the secret into a log; and if you record failed attempts, record that the check failed rather than what was tried.
6. Narrow what it can even see
Demanding a secret decides who may ask. It does not decide what can be handed over. A program that will happily open any file it is told to is one typo away from opening something it should not.
The fix is to work out where a requested file really is, confirm it sits inside the one folder you meant to share, and refuse everything else. The shape of that check, and the tests that prove it works, are the subject of the next guide, because a check written afterwards is a guess.
7. Put it on a calendar, because you will not notice on your own
What this does: keeps a short written list of what each machine offers, next to the machine it describes.
Why a one off check is not enough: the reason mine sat open for months is that nothing ever reminded me to look. An inventory you run once is a photograph, and your machine keeps changing after the picture.
# exposure.md, kept with the machine
# helper program -> this computer only, no secret needed
# media server -> whole network, secret required, last checked 2026-09
# repeat steps 1 and 2 every few months, and after adding anything new
This finds what is waiting right now, on the machines you remembered to check. It will not find the program on the box you forgot you still had running. Start the list anyway. A list with gaps beats a memory with none.
Related reading: prove nothing is using it before you switch it off is the discipline that stops this cleanup from quietly breaking something days later.
This page in the original Kyber Cypher voice: Your own service was handing out your keys