Skip to content
[015]2026.06.01log

The Door That Was Open

What I found in the pre-launch security check

As the launch drew near, one thing kept nagging at me. Security.

A company has a security team. There are colleagues who review the code, and before release they do something called penetration testing. I have none of that. The chance that I—who can't read code—could find a security hole with my own eyes is, honestly, none.

So I had AI do it. I assigned it a role. "You are a senior security reviewer. Payments, authentication, data access—doubt everything and verify everything."

The review results came back. Payment verification is solid. Encryption is by the book. Authentication is properly checked on the server. I read this far and felt relieved. And on the next line, the relief ended.

One critical problem. Eight database functions are open to anyone.

The explanation was this. The database has functions that do things like "retrieve this user's list of notes." Put a user ID into the function and that person's data comes out. The problem was the permission to call these functions. Originally, only the server should be able to call them. But when you create a function, the database gives execute permission to everyone by default. I didn't know that default, so I didn't change it.

As a result, someone not even logged in could put in an arbitrary user ID, call it, and get that person's list of notes, topics, and ebooks. I checked whether it actually worked. It did. The door was really open.

Cold sweat ran down my back. I'd gone on about encryption and whatnot to protect users' data, and the back door was open. That no one had come through that door was purely luck. The luck of the service not being known yet.

The fix itself took less than a day. I revoked the permissions on the eight functions and locked them so only the server could call them. I confirmed they were locked three times.

I learned two things that day.

One. A default is not a design. If the database leaving the door open is the default, locking it is my job. The excuse "I didn't know" doesn't work in my house. If I don't know, the service runs with no one knowing.

Two. The same mistake should become a checklist. These eight functions were built one by one over several months, all repeating the same mistake. Had I caught it in the first function, the other seven wouldn't exist. So I added a line to the development-rules document. When making this kind of function, always revoke permissions first. The next function I make must pass this checklist to be born.

Security isn't a feature, so it isn't visible on screen. Nothing happening even when you do it well—that's security. I spent a day to create a state where nothing happens, and I think that day was one of the best-spent days of this journey.


🔧 Technical Terms in This Episode

IDOR (Insecure Direct Object Reference) A vulnerability where swapping in an ID that points to someone else's data lets you view it directly. "I changed my order number 1001 to 1002 and saw someone else's order" is the classic example.

RPC (Remote Procedure Call) A method of calling functions pre-built in a database or server from outside. The stage of this incident.

REVOKE / GRANT Commands to revoke (REVOKE) and grant (GRANT) database permissions. The core of this fix was "revoke from everyone, grant only to the server."

Penetration Test A security check that tests whether something can actually be broken into, from an attacker's standpoint. This time AI played that role, and it actually broke in.