Learn / Security
Least privilege
Lesson 28 of 37 · 8 min read ·
The principle
Every user, service and credential gets the minimum access needed to do its job, and no more.
The reason is not distrust. It is blast radius. Compromise is a matter of when: a leaked token, a dependency with a backdoor, a phished laptop, a server-side request forgery. Least privilege decides whether that incident is "an attacker read one bucket" or "an attacker owns the account".
Design for the assumption of compromise
Assume this credential will leak. Now ask: what can the holder do?
If the answer is "read every customer record", the design is wrong regardless of how careful you are. Good design makes the honest answer boring: "read the last 24 hours of one tenant's order data, for one hour, from one IP range."
Three dimensions to shrink:
- Scope — which resources, which actions.
- Time — how long the credential is valid.
- Context — from where, under what conditions.
Practical rules
Separate read from write. Your analytics dashboard, reporting job and BI tool need read-only database users. Most application code that reads does not need DELETE. This one change removes an entire class of catastrophic accident, including the accidental kind.
One identity per service. Not one shared credential across five services. When a credential leaks you need to know which service to fix, and when a service is retired you need to revoke exactly its access. Shared credentials are never revoked because nobody knows what will break.
Prefer workload identity over long-lived keys. Every major cloud lets a container or function assume a role automatically, with credentials rotated by the platform every few hours. This removes the secret entirely — there is no key to leak. If you are still using static access keys for service-to-service auth, that is the highest-value thing to change.
Short lifetimes. An access token valid for 15 minutes with a revocable refresh token beats a token valid for a year. See OAuth, JWT and PKCE.
Scope tokens to what the feature needs. If your integration only reads calendar events, request the read scope. Over-broad scopes are also a trust signal to your users — a request for full account access to do one small thing is a red flag they are right to notice.
Deny by default. Access control lists that start from "allow everything, deny some things" fail open. Start from deny and add.
Separate environments completely. Separate accounts or subscriptions, not just separate resource names. A staging credential must not touch production data. This is also the cleanest protection against the "I thought I was on staging" incident.
Just-in-time for humans. Standing production admin access for every engineer is the most common over-privilege in practice. Time-bound elevation with a reason and an audit record is achievable now and removes most of the risk.
Where it goes wrong
- The wildcard.
"Action": "*"orGRANT ALL"temporarily", during setup, permanently. - Copying a role. Someone needs a new service account, copies an existing one, and inherits permissions nobody has audited in three years.
- Permission creep. People change teams; access accumulates. Review quarterly and revoke aggressively — if removal breaks something, that is information you wanted anyway.
- The admin API key used by everything because scoping it was fiddly on a deadline.
Verify from the other side
The important question is not "does it work?" but "what else does it let me do?"
Take a service credential and try something it should not be allowed to do. If it succeeds, you have found over-provisioning. Cloud providers help here: IAM Access Analyzer and equivalents report which granted permissions were never actually used, which is the fastest path to trimming a role safely.
Gotchas
- SSRF turns an over-privileged instance role into a full breach — the classic path to cloud credentials via a metadata endpoint. See the OWASP Top 10.
- Database users are often forgotten. Most apps run as a superuser that could drop the schema.
- Logging and monitoring tools frequently get broad read access to everything, including secrets in logs.
- Least privilege without an audit log is unverifiable. You need both.
Prove you know it
Pick the credential your main application uses for its database. List everything it is permitted to do. Then list what it actually does. The difference is your attack surface — and usually it includes DROP TABLE.