JIT access patterns and pitfalls
JIT is easy to adopt and easy to fake. A walkthrough of the patterns that actually reduce standing privilege — and the ones that just move it around.
Just-in-time access, as a phrase, is doing a lot of work. Every PAM product claims it. Every compliance framework rewards it. Every security program has a slide on it. And yet in production, the majority of 'JIT access' is something closer to 'access that required a ticket once and has been live ever since.' The gap between what JIT promises and what it usually delivers is worth looking at directly.
Done well, JIT does exactly what the name suggests: it collapses the window during which a privilege exists to the window during which it is being used. The privilege is granted on demand, used, and revoked. Standing privilege shrinks to approximately zero. Done poorly, it is a rubber stamp on top of the access model you already had.
Pattern one: approval-gated elevation
The simplest JIT pattern is an approval workflow that grants a time-bound entitlement. An engineer requests access to a target, a peer or manager approves, and the entitlement lives for a fixed window — 30 minutes, 2 hours, a shift. At the end of the window, the entitlement expires automatically.
This works well when the approval is meaningful and the window is short. It fails when the approval is automatic (a bot that always approves), when the window is long (24 hours is not JIT, it is next-day access), and when the revocation is manual and therefore skipped. The quick test: do you have any entitlements older than 24 hours that started their life as JIT grants? If yes, the revocation is broken and the pattern has silently degraded to standing access.
Pattern two: break-glass with loud audit
Break-glass is the designated emergency path. It is JIT by definition — nobody holds break-glass credentials day to day — but it is a specific subtype with specific rules. Break-glass should be loud. Everyone on the security team should know within minutes when it is used. Every use should generate an incident review, even if the incident itself was trivial.
The pitfall here is 'quiet break-glass' — an emergency path that is used routinely because the ordinary path is slow or broken. When that happens, the emergency path has become the ordinary path. The answer is not to make the emergency louder; it is to fix the ordinary path so nobody reaches for the emergency unless something is actually on fire.
Pattern three: change-bound access
Change-bound access ties an entitlement to a change ticket or a specific maintenance window. The rule reads: 'access to database-42 is granted while change CHG-8871 is in the implementing state.' When the change moves to closed, the access evaporates. When the change window expires, access evaporates. This pattern composes well with approval workflows because the approval is the change approval, which is already happening.
policy "change-bound-db-access" {
subject {
idp_group = "db-engineers"
}
target {
host_tag = "tier:prod-db"
}
condition {
change_ticket {
state = "implementing"
ticket_ref = request.ticket_ref
}
}
obligation {
record_session = true
max_duration = "change.window"
}
}Pattern four: scoped ephemeral credentials
The fourth pattern is less about workflow and more about credential shape. Instead of granting access to a long-lived account, the gateway mints a short-lived credential scoped to exactly the target and scope the session needs. A database session gets a role that can read the two tables the engineer asked for, expires in an hour, and cannot be replayed. An SSH session gets a certificate that is valid for the duration of the session and nothing else.
This pattern is the one that most often gets skipped, because it requires the gateway to broker credentials on the target side, not just the user side. It is also the pattern with the highest payoff. Credentials that do not exist cannot leak.
The pitfalls, in one list
- Long windows. If your 'JIT' window is eight hours, you have standing access with extra steps.
- Automatic approvals. A workflow where every request is approved by a bot with no human in the loop is audit theater, not JIT.
- Forgotten revocation. If revocation is manual, it will be forgotten. Revocation must be the default case that fires without anyone doing anything.
- Session scope drift. A JIT grant that lets the user reach the target and then anything the target can reach is not really scoped. The scope is the transitive closure, not the initial hop.
- Parallel standing paths. A JIT grant to a target that also has a standing path is a JIT grant to nothing; the attacker uses the other path.
How to tell real JIT from theater
One question: at 03:00 on a random Tuesday, how many accounts can reach production? Real JIT answers 'close to zero, unless someone is actively working.' Theater answers 'the same number as during business hours, because the grants are still live.' The shape of the answer tells you which one you have.