The Security Rules I Make Every AI Coding Agent Follow

Distilled from a real backend build, proven under real review and real mistakes, not copied from a checklist.On the Soulful Ledger backend build, I deliberately broke the tenant scoping clause in one query, just to see what would happen. The test suite stayed green. Every test passed. That’s the…

Distilled from a real backend build, proven under real review and real mistakes, not copied from a checklist.On the Soulful Ledger backend build, I deliberately broke the tenant scoping clause in one query, just to see what would happen. The test suite stayed green. Every test passed. That’s the moment I learned a green test suite proves nothing on its own. It only proves something once you’ve watched it catch a real break, and then fixed the break back.That single failure is where most of what follows came from. Not a framework borrowed from somewhere else. These are wounds, distilled into defaults, from building a real multi-tenant system with AI agents doing a lot of the typing.Every query is parameterized, no exceptions$1, $2 syntax, never string interpolation into SQL. Not "just this once for the admin panel." Not "just for this one internal script." The exception is always where the injection ends up living, and an AI agent generating code at speed will happily write the unsafe version if you don't tell it not to, every single time you ask.I watched this happen on an early Soulful Ledger endpoint. An agent building a quick internal reporting query dropped a raw f-string straight into the WHERE clause, because it was faster to write and nothing in the request had mentioned parameterization. Caught it in review, not in production, which is the only place that catch is allowed to happen.Tenant scope never comes from the client, and never from the modelIf a multi-tenant boundary exists, the query enforcing it needs the scope value baked into its WHERE clause, computed server-side, before the query ever runs. Not from a request body. Not from a URL parameter. Not from anything an AI model outputs, even if the model is only echoing back a value you gave it three turns ago.Here’s the test that actually proves it: deliberately break the scoping clause, confirm the suite catches it, then restore the clause. That’s the test I ran on Soulful Ledger, the one that came back green with a broken clause still in place. Twelve passing tests told me nothing until I watched one of them fail on purpose.AI never gets raw access to the data it’s protectingIf an AI needs to answer questions from a database, it doesn’t get a query tool. It gets a fixed, named, reviewed set of read-only functions, built the same way a human-reviewed API endpoint would be built.The tool schema exposed to the model never includes a scope or tenant field. That value gets injected server-side, after the model has already made its choice, never accepted from the model’s own output.The agent writing the code doesn’t hold the keysAn AI coding agent never carries a database owner or superuser credential across a session. It can generate the migration. It can tell you exactly what command to run. The human runs anything elevated directly, by hand. The agent works with the same restricted, least-privilege credential the running application itself uses, nothing more.This shows up in small decisions too. When I built the security audit stack for client engagements, the exploitdb server runs stdio-only, no HTTP port, no API key sitting around to leak. Canopy Guard, the free audit tool, stays external-only and uncredentialed on purpose, a completely separate boundary from anything that touches a client’s real environment. Two different products, two different trust levels, and the line between them isn’t an accident.A green test suite is not proof of anythingEvery security-relevant guarantee needs a test that could actually fail, and most teams never check that it can. Twelve passing tests prove nothing by themselves. What proves something is deliberately introducing the break the test is supposed to catch, watching the right thing go red, then fixing it.The stronger version of this is proving the negative. “This works for the right tenant” is a weak claim. “This returns nothing for the wrong tenant, even when the wrong tenant’s data would rank as the best possible answer” is the claim worth building a test around.If only one file in your codebase should ever query a sensitive table, write a test that fails the moment any other file does. That’s a chokepoint test, and it catches the mistake before it ships instead of after.Where this actually leaves youI still run the client work, the builds, the calls, same as before any of this was written down. None of it changed the pace. What changed is that I don’t report something as done anymore without having actually run it and watched it behave correctly, and I don’t let a large pile of adjacent, verified work stand in for testing the one thing that hasn’t run yet.This approach costs time. It’s slower than trusting the first green test suite you see. It’s also the only way I’ve found to know the AI-assisted parts of a build are actually safe, instead of just hoping they are.This story is published under the Generative AI publication. Connect with us on LinkedIn and follow Zeniteq to stay in the loop with the latest AI stories. Let’s shape the future of AI together!The Security Rules I Make Every AI Coding Agent Follow was originally published in Generative AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

Source: Generative AI Pub — Published — Category: Image AI

🔗 Read full article on Generative AI Pub →