Problem/Motivation

GrantInventory::revokeJti() marks a grant as spent by writing a redemption counter that expires. When the caller sends no ttl, the mark lasts DEFAULT_KILL_TTL, 30 days. It also removes the grant from the inventory, so the grant no longer appears in the list.

A grant can live longer than that. If its expiry is more than 30 days away, the kill mark expires first. The redemption counter starts again from zero and the signed URL can be redeemed until the grant's own expiry. The revoke returned success, the grant is gone from the operator's list, and nothing shows it came back.

The bulk revoke path uses the same default.

Steps to reproduce

  1. Configure a gated field with a usage limit and a time to live above 30 days, and mint a grant.
  2. Revoke the grant by id without a ttl.
  3. Read the expiry stored for the redemption counter: it is 30 days out, before the grant's expiry.

Found by reading 1.x. The expiry arithmetic is reproduced in a kernel test; redemption after the mark lapses has not been exercised end to end.

Proposed resolution

  • In revokeJti(), read the grant's stored expiry and keep the kill mark until at least that time plus a margin. A caller-supplied ttl may extend the mark and may not shorten it below the grant's remaining life.
  • Apply the same rule to bulk revoke.
  • When the inventory has no record of the grant, keep today's default.

Remaining tasks

  • Kernel tests: a 90-day grant revoked with no ttl and with a short ttl keeps a mark past its expiry; a grant past the mark cannot be redeemed; bulk revoke behaves the same.
  • Document the rule in the revoke section of the README.

API changes

None. A short ttl on revoke is raised to the grant's remaining life.

Comments

jmcerda created an issue. See original summary.

jmcerda’s picture

Status: Active » Fixed

Committed to 1.x; ships in 1.10.0. Reproduced end to end with a real mint, revoke and download and a movable clock: before the fix a grant with a 90-day life was served again once the 30-day mark had expired. The kill mark now lasts until the stored expiry of the grant plus one hour. A caller ttl can lengthen the mark and cannot shorten it. A grant the inventory does not know keeps the 30-day default. Bulk revoke uses the same rule. Review found a second case: a repeat revoke with a short ttl overwrote the long mark, because the first revoke had already removed the inventory row. Each mark now records its own expiry, so a later revoke cannot shorten it.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • jmcerda committed 2c3e0518 on 1.x
    fix: never shorten an existing revoke kill mark (#3624450)
    
    Revoke...

  • jmcerda committed ec96889a on 1.x
    fix: keep a revoke kill mark until the grant itself expires (#3624450)...

  • jmcerda committed 2c3e0518 on cursor/file-gate-uninstall-kv-cleanup-42ea
    fix: never shorten an existing revoke kill mark (#3624450)
    
    Revoke...

  • jmcerda committed ec96889a on cursor/file-gate-uninstall-kv-cleanup-42ea
    fix: keep a revoke kill mark until the grant itself expires (#3624450)...