store: ids are reused after a hard delete; audit signed values that name them #306

closed cmc opened this on 2026-09-29 06:05 UTC · security

Discussion

cmc 2026-09-29 06:05 UTC

repos.id and users.id (and most tables) are INTEGER PRIMARY KEY without AUTOINCREMENT and rows are hard-deleted, so deleting the newest repository or account lets the next one take its id. The #295 review found a reply-by-mail token bound to a deleted repository posting into the new one with the same id; that path now checks created_at against the token's mint time.

Other signed or cached values that name an id need the same check or a non-reused id:

  • LFS tokens (repo:key:keypin:op:exp; the key pin covers the key, not the repository)
  • web session and login-link rows, push device tokens, webhook delivery rows, cursors
  • anything in the audit log or notifications that is later resolved by id

Options: AUTOINCREMENT on the parent tables (a migration per table), or a created_at / generation check wherever a stored or signed id is resolved.

closed by cmc in commit 9ff63ee5ef: wiki, changelog: ids not reused after a delete

2026-09-29 15:59 UTC

referenced in commit a6378c178c by cmc: store: deletes take grants and deploy keys naming the deleted row

2026-09-29 15:59 UTC

referenced in commit 970614872d by cmc: store: build ids from a high-water mark

2026-09-29 15:59 UTC

referenced in commit 7af5f9d750 by cmc: store: AUTOINCREMENT ids for accounts, orgs, repos, keys, tokens, queues

2026-09-29 15:59 UTC