Blog
3 min read

The Principle of Least Privilege, Explained for App Builders

Give every user, service, key and AI agent only the access it needs — nothing more. What least privilege means, and practical examples for databases, API keys, cloud accounts, servers, team members and AI coding agents, so one mistake or breach can't take everything down.

The principle of least privilege is simple to say: every person, program and key should have only the access it needs to do its job — and no more.

It's not about distrust. It's about limiting the damage when something goes wrong: a leaked key, a bug, a compromised account, or an AI agent that misunderstands an instruction.

An everyday analogy

A hotel gives a guest a key card for their room, not a master key. If the guest loses it, one room is at risk, not the whole building. Least privilege is giving out room keys instead of master keys.

In practice

Your database

Your app probably connects as one database user with full rights — able to drop tables, read everything, create users. Instead:

  • App user — can read and write its own tables. Can't drop tables or change permissions.
  • Migration user — can change the schema, used only during deploys.
  • Read-only user — for analytics, dashboards, and AI tools that only need to look.
CREATE ROLE app_readonly WITH LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE myapp TO app_readonly;
GRANT USAGE ON SCHEMA public TO app_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_readonly;

(Postgres roles and permissions)

API keys

  • Use restricted keys where providers offer them (Stripe restricted keys, fine-grained GitHub tokens, scoped cloud credentials).
  • One key per app and environment, so you can revoke one without breaking everything.
  • Never put secret keys in the browser. (Keep API keys out of an AI-built app)

Users in your app

Users should only reach their own data. Admin abilities belong to admins. Enforce it on the server for every request — hiding a button isn't access control. (Role-based access control, IDOR explained)

Servers

  • Run your app as a dedicated, unprivileged user, not root.
  • Containers run as non-root. (Dockerfile explained)
  • Open only the ports you need. (UFW basics)
  • SSH keys for the people who need access, removed when they leave.

Team members

Not everyone needs owner access to your hosting, domain registrar, payment provider and database. Give people the role their job needs, and review it when roles change.

CI/CD

Pipelines often hold the most powerful credentials of all. Scope them tightly; use short-lived credentials where possible; restrict production deploys to protected branches. (GitHub Actions secrets)

AI coding agents: least privilege matters most here

An AI agent with a terminal can run any command its permissions allow. If it can reach your production database with an admin connection string, then one misunderstanding — "clean up the old test data" — can delete real data. (How to stop an AI agent deleting your production database)

Apply least privilege to agents:

The trade-off

Least privilege adds a little friction: separate users, more keys, the occasional "permission denied". That friction is the point — it's the difference between "we lost a test table" and "we lost the company's data".

Start with the highest-impact areas: production database access, payment keys, and anything an automated agent can touch.


EasySpawn gives each server its own isolated VM and keeps databases off the public internet, so Claude Code and your apps work with only the access they need. See how it works or join the waitlist.

Related: How to Stop an AI Agent From Deleting Your Production Database · Postgres Roles and Permissions · Role-Based Access Control · Authentication vs Authorization

Keep reading