Everyone agrees on least privilege. Then a pipeline breaks at 11pm, someone grants the service account broad access to ship the fix, and the grant never comes back. For non-human identity, least privilege is not a policy problem. It is an operations problem: the access drifts up under deadline pressure and nothing pulls it back down.
So skip the theory. Here is what least privilege for non-human identity actually requires in practice, and where it usually fails.
Where least privilege breaks for machines
- Grant-and-forget. Permissions go up to fix an incident and stay up because removing them feels risky.
- Copy-paste roles. A new service account inherits an existing over-broad role because it is faster than scoping a new one.
- No expiry. Human access often ends with a session. Machine grants are standing by default, so least privilege erodes silently over months.
The pattern is always the same: privilege ratchets up easily and down almost never.
The operational fix: make grants temporary by default
The single change that does the most is to flip the default. Instead of standing access you periodically try to trim, give time-boxed access you grant on demand. When a grant expires on its own, the drift stops accumulating. Least privilege becomes the resting state instead of a goal you chase.
This only works if the temporary grant is enforced somewhere the workload cannot quietly extend it. A self-managed expiry inside the service is not a control.
Enforce least privilege on the access path
The architectural requirement: the policy that decides what a non-human identity may reach has to run outside that identity's own process. If the agent or runner can reconfigure its own scope, least privilege is advisory. The decision point belongs on the connection.
hoop.dev is an open-source gateway between identities and infrastructure. A non-human identity reaches a specific database, cluster, or service through it, the grant is scoped to that connection and can be time-boxed with just-in-time access, and every command is recorded under a named principal. The runner cannot widen its own scope, because the scope lives on the gateway, not in the runner. That is least privilege you can actually hold. The grant and approval model is in the getting-started guide.
A short operating recipe
- Default a new non-human identity to no standing access.
- Grant access just in time, scoped to one connection, for the duration the job needs.
- Record every command so you can audit whether the scope was right.
- Review the records, not the role names, to find scopes you can tighten further.
The records are what make tightening safe: you trim what was never used, not what you guess is unused. The identity-aware model is described on the hoop.dev site.
Two pitfalls to expect
First, the incident exception. The fastest way to lose least privilege is the emergency grant that becomes permanent. If your only tool is a permanent role edit, every incident widens access for good. Just-in-time access gives you an emergency grant that expires on its own, so the exception does not survive the incident.
Second, the shared role trap. Teams reuse one broad role across many service accounts because creating a scoped role per workload is tedious. The cost shows up later: you cannot tighten the role without risking every account that shares it, so it stays broad forever. Scoping access on the connection, per principal, breaks that coupling. One identity's grant can shrink without touching another's.
Neither pitfall is solved by writing a stricter policy. Both are solved by making the tight grant the easy, default path and the broad grant the deliberate, temporary exception.
FAQ
Is least privilege realistic for fast-moving teams?
Yes, if grants are temporary rather than standing. The friction people resent comes from approval queues for permanent access. Just-in-time, scoped grants remove most of that while keeping the bound.
How do we right-size a service account's scope?
Use its command-level record. Permissions it never exercised over a full cycle are candidates to remove. Behavior beats guesswork.
To enforce least privilege for non-human identity on the connection itself, read the open-source gateway on GitHub.