Guide 085 checklist

How to review permission changes for stale access

Review stale access after permission changes across sessions, jobs, and result delivery, and align operator promises with the revocation behavior you can verify.

Review a permission change by asking when the change becomes authoritative and which later operations can still use the old grant. Choose a concrete revocation, record its committed time and expected denial boundary, then inspect fresh API reads, writes, exports, caches, jobs, tokens and file links using an authorized synthetic account. For each surface, identify the authority source, the maximum permitted staleness, the actual decision point and the observed result. A role-edit screen showing “saved” is not proof that every service stopped access. A missing response is also not proof: check whether the request reached the right path and whether content or a side effect escaped before denial. Previously delivered data cannot be taken back.

OWASP's authorization guidance calls for permission checks on every request. Its policy and data distribution guidance asks teams to define which source owns a grant and how quickly a change must affect decisions. The right revocation mechanism depends on that explicit time requirement; a token's expiration date by itself does not define acceptable exposure.

Illustrative case: project access removed during an export

Illustrative case, not a customer incident: Northstar Metrics gives Priya a Cedar project-reader grant for C-17. She can open report R-40, download its attachment and request a project export. At 10:00 UTC, a project owner removes Priya's grant. The UI confirms the change. At 10:01, Priya still has a signed-in browser session, an old access token, a cached report view, and an export job queued at 09:59. A download link was issued before removal.

The policy owner specifies the review target: after the grant change is durably committed, new protected operations must not deliver C-17 content to Priya. The review separately records any already-started transfer and any data already in her browser. Define whether “new” means admission, commit or delivery: the worked protocol below orders publication and revocation commits, then authorizes each later download. This target is an example, not a promise that every system can meet it. If the application allows a bounded propagation interval, write that interval and its exception process before assessing behavior. A vague “eventually revoked” statement cannot be validated.

The key questions are different for each surface. Does the API read current membership or a cached role? Does the export worker recheck the original user's live project grant before gathering data and before releasing a file? Can an old bearer link still fetch the attachment? Does another account's role accidentally keep the C-17 grant alive? The answer should come from the actual request path, not a global assumption about tokens.

Use a revocation ledger

Surface Authority and freshness question Expected post-change observation Evidence owner
Report detail and search Does each new request check Priya's current C-17 grant before any result or snippet? No protected content, title, count or cached response. API owner
Edit or comment Is the write conditional on a current grant, including the point of mutation? No write ordered after the authoritative removal; document how an already-committed write is treated. Service owner
Export queued before removal Does the worker revalidate when it starts and before it publishes a file? No new file delivery after revocation under the stated policy. Job owner
Existing session and token Are old claims treated as current grants, or is live state consulted? Old session cannot authorize a new protected operation. Identity/API owner
Cache Is the cache entry keyed and invalidated for permission version and audience? No stale R-40 content returned on a new request. Platform owner
File link Does opening the link repeat authorization, or is it a bearer capability with an expiry? Outcome matches the documented revocation policy; any residual window is reported. Storage owner

This ledger makes each team's responsibility and the evidence gap visible. A single “logout worked” observation cannot answer the export or direct-download rows.

The interesting race is between checking and publishing

Checking a grant when a worker starts still leaves a gap. In the synthetic sequence below, the worker starts before the removal and publishes afterward:

09:59:50  enqueue export E-7 for Priya / Cedar / C-17
09:59:55  worker reads grant version 41: allowed
10:00:00  removal commits as version 42
10:00:03  worker finishes file and publishes its download record

A second check at 10:00:02 helps, but another removal could occur between that check and publication. “We check twice” is not a concurrency argument. To meet a strict policy, the operation that makes the file available must be ordered against the grant change. The required mechanism depends on where policy and publication state live.

For a design that stores grant state and publication metadata in the same transactional database, an illustrative protocol is:

build artifact privately; do not issue a link
begin transaction
  lock the authoritative grant row
  require grant is active for actor, project and export action
  require job still belongs to this tenant/project and is not cancelled
  create publication record referencing the private artifact
commit

The removal path must acquire the same relevant lock before changing the grant. Both paths must agree on lock order and error handling. This is design pseudocode, not a tested database implementation. If removal commits first, publication sees the removed grant and fails. If publication commits first, the record existed before removal; subsequent downloads still need current authorization to meet the stated delivery policy. A publication record is not a perpetual download permit.

If grants live in a separate service, a local database transaction does not magically include them. You need an explicitly designed authorization reservation/fence or a measured propagation window accepted by the policy owner. Until that mechanism is established, report “strict revocation at publication unproven.” Do not present a version number in a job payload as a solution unless publication compares it with authoritative state under the required ordering.

Read the job states as exposure states

State when removal commits Action under this example's policy Remaining exposure
Queued Deny admission to content processing when authority is rechecked Metadata already in the queue
Running with private intermediate file Stop further protected work at the enforced checkpoint; do not publish Task-local copy requires controlled cleanup
Generated but unpublished Deny publication; schedule cleanup Private artifact until cleanup completes
Published behind live authorization Deny Priya's next download Other authorized readers may still use it
Issued as a direct bearer link Apply the link's actual revocation mechanism May remain usable independently of the app grant
Already downloaded Prevent future service delivery Received copy cannot be recalled

A cleanup failure must not reopen a revoked download. Keep access denial and artifact retention as separate states. Likewise, an old export's existence need not mean the file was delivered to the removed user.

For an S3 presigned URL, the storage service checks the signature, applicable policy and effective expiry; it does not call your application to ask whether Priya still belongs to C-17. AWS documents effective expiration and credential lifetime. If immediate per-user removal is a requirement, an independently usable URL needs a suitable revocation design or must be replaced with an authorization-mediated delivery path. Shortening expiry merely bounds a residual window.

Separate user-dependent work from durable delegation

Some exports belong to the organization after an authorized person starts them. That can be a valid product policy: a scheduled financial export continues for the company's authorized finance team even if its creator leaves. The worker then acts under a narrowly scoped organizational delegation, not the creator's surviving personal grant. Delivery to the removed creator must still stop.

Write down which model E-7 uses before adjudicating it. Under user-dependent authority, version 42 invalidates further protected work. Under explicit organizational delegation, processing may continue for permitted recipients; the job owner, purpose, expiry and cancellation authority must be known. A generic service role with access to everything is not a documented delegation.

The practical review now has three precise questions: what orders publication against removal, what authorizes each later delivery, and who owns work after its creator loses access? These reveal more than checking whether logout changes the browser screen. Human session revocation is a related credential problem; this review stays focused on the application permission's effect on work and outputs.

Make the outcome precise

For Northstar, a filled decision note might read:

  • Change: Priya's C-17 reader grant removed in Cedar at authoritative version 42, 10:00 UTC.
  • Required effect: no new C-17 content delivery after version 42 commits.
  • Observed: detail route denied at 10:00:04; search route not yet reviewed; queued export issued an independently usable bearer download capability to Priya at 10:01 using the enqueue grant; that capability and a pre-issued link delivered synthetic C-17 content after removal.
  • Decision: stale-access exposure supported for export and bearer-link path under this policy; detail-route denial is limited counterevidence, not global closure.
  • Next owner: job owner enforces shared grant/publication ordering or an equivalent authoritative fence; storage owner requires fresh authorization for subsequent delivery or obtains approval for a precisely bounded residual window; reviewer checks both the ordering race and later delivery at the new revision.

These are invented observations to show the form of a review record. A real report must include actual traces, build identifiers and permission evidence. If an old token fails but the queued job's original delegation is still valid by explicit policy, do not call it a bug until the policy's expiry and scope have been checked. If a route could not be exercised, mark it unreviewed. If a control is claimed but its cache age or decision point is unknown, keep that row inconclusive.

Separate the revocation promise from the user interface

Northstar's permission screen should describe the boundary the service can actually enforce. If the design stops new application-mediated downloads but previously issued bearer links remain usable for a bounded period, the operator needs that distinction when removing access. The review should compare the interface wording with the ledger rather than accepting “access removed” as a complete technical claim.

A useful internal handoff identifies the authoritative removal event, the surfaces that consult it, and the surfaces that need a different mechanism. That allows the product and platform owners to choose a proportionate next step: shorten an accepted residual window, change delivery architecture, or make the limitation visible. The security reviewer supplies evidence; the policy owner decides which behavior the product promises.

Also inspect restoration. If Priya is later granted access again, the new grant should follow the current policy and scope. Restoration need not revive every old job or link merely because the same username reappears. In the synthetic workflow, the owner should decide whether a previously cancelled export requires a new admission or may resume under a new explicit decision. Do not let an old job's stored grant silently answer that question.

These additions keep the review useful beyond the single removal event. A complete result explains both the technical ordering and the operator's practical choices, while preserving the distinction between stopping future delivery and recalling information already received.

This week, pick one permission removal and fill the six-row ledger with the current owner of each decision. Start with the shortest-lived data path and the longest-lived artifact. For the wider boundary review, use the multi-tenant access control method. If the stale decision starts with a caller-supplied account selector, use tenant ID spoofing.