Concept · Application & cloud security
Least privilege
Give each person, service and job only the access it needs, for only as long as it needs it.
3 minprinciple of least privilegeRBACblast radius
The principle of least privilege says every identity (a person, a service, a CI job, a container, an AI agent) should have only the permissions its task requires, and only for as long as it needs them. You can't prevent every compromise. What you can control is the blast radius: what an attacker can do with the identity they took over.
In practice
| Where | Too broad | Least privilege |
|---|---|---|
| Cloud IAM | AdministratorAccess on the app's role | s3:GetObject on arn:aws:s3:::invoices-prod/* only |
| Database | App connects as the owner/superuser | App user can SELECT/INSERT/UPDATE its tables; migrations use a separate role |
| Kubernetes | Pod uses a ServiceAccount bound to cluster-admin | Namespaced Role with the few verbs it needs; automountServiceAccountToken: false when unused |
| CI | Workflow token with write access to everything | permissions: contents: read by default, elevated per job |
| Containers | Runs as root with all capabilities | Non-root user, drop: [ALL], read-only root filesystem (namespaces and cgroups) |
| AI agents | A tool that runs arbitrary SQL or shell | Narrow, read-only tools scoped to the current user (the tool-use loop) |
The time dimension
Privilege that never expires gets stolen eventually. Prefer:
- Short-lived credentials issued on demand over long-lived keys. See short-lived credentials with OIDC.
- Just-in-time elevation for humans: request production access for an hour, with a reason and an audit trail, instead of having it permanently.
- Regular cleanup: remove unused roles, keys and permissions. Cloud providers can report which granted permissions were never used, so you can trim from real usage instead of guessing.
Getting there without breaking things
- Start from nothing and add what's needed, rather than starting from
*and planning to tighten later. Later rarely comes. - Separate identities per workload. If five services share one role, each one has the union of all five's permissions.
- Separate read from write, and production from everything else.
- Use policy as code and review it like any other change. Lint for wildcards like
Action: "*"andResource: "*". - Log every use of high privilege and alert on the unusual ones.
Least privilege is the standard answer to the "E" in STRIDE, and it's what turns a stolen token from an incident into an inconvenience.