Skip to content

Timed-out destructive requests keep mutating Redis (zombie delete-after-recreate data loss) #13

Description

@Coriou

Found by adversarial audit @ 261d00b, survived refutation (conf 0.88).

Mechanism: timeoutMiddleware (src/middleware/timeout.ts:28-41) resolves Promise.race, returns 504, and attaches only a log-and-swallow .catch — the handler keeps running with no cancellation. Multi-step mutating routes have no generation guard between steps: DELETE /delete-namespace (namespaces.ts:37-40: dropIndex → deleteKeysByPattern → SREM×2), POST /reset (reset.ts:82-86), /rename-namespace (namespaces.ts:88-113). deleteKeysByPattern (keys.ts:91-112) is a serial SCAN(100)+DEL loop capped at 10k iterations — >30s realistic at ~10^5+ keys or during any Redis stall (enableOfflineQueue:true redis.ts:27 also queues commands across reconnects).

Data-loss interleave: caller gets 504 on delete-namespace of large N → assumes failure → re-upserts into N (recreates idx:N, SADDs registry) → zombie's open SCAN cursor DELs the fresh v:N:* keys and its trailing SREM unregisters N again. Client saw 200 for the upsert; data silently gone. Upserts are idempotent-safe; delete/reset/rename are not.

Fix direction: cancellation/generation token checked between steps of multi-step routes, or abort work when the response has been sent; optionally serialize destructive namespace operations.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: highHigh-impact; tackle next

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions