decode_cursor length check accepts an over-long cursor instead of refusing it as malformed #91

Closed
opened 2026-09-23 06:57:04 +00:00 by yuris · 0 comments
Owner

Context

The independent review of the pagination work for PR 83 identified that the cursor decoder checks only a minimum size. The externally visible refusal is already cursor_expired, but the length predicate does not enforce the exact fixed-size encoding it is intended to validate.

In src/api/pagination.rs, decode_cursor checks whether the decoded bytes are shorter than PAYLOAD_BYTES plus the 32-byte HMAC tag. An otherwise valid cursor with trailing bytes therefore proceeds to HMAC verification instead of being rejected as malformed input.

What to change

  • Require the decoded cursor to have exactly PAYLOAD_BYTES plus 32 bytes.
  • Cover both a valid cursor with trailing bytes and an under-length cursor. Both must be refused through the normal API error mapping as cursor_expired, HTTP 422 and CLI exit code 2.
  • Keep unrelated pagination behavior unchanged.

Acceptance criteria

  • A valid cursor with appended bytes is rejected as malformed input before signature verification.
  • An under-length cursor is also rejected.
  • The consumer-visible error remains cursor_expired, HTTP 422 and exit code 2 through the shared mapper.
  • Existing pagination behavior remains unchanged.

Blocked by

None. The check was introduced with the paginated read work in PR 83.

## Context The independent review of the pagination work for PR 83 identified that the cursor decoder checks only a minimum size. The externally visible refusal is already cursor_expired, but the length predicate does not enforce the exact fixed-size encoding it is intended to validate. In src/api/pagination.rs, decode_cursor checks whether the decoded bytes are shorter than PAYLOAD_BYTES plus the 32-byte HMAC tag. An otherwise valid cursor with trailing bytes therefore proceeds to HMAC verification instead of being rejected as malformed input. ## What to change - Require the decoded cursor to have exactly PAYLOAD_BYTES plus 32 bytes. - Cover both a valid cursor with trailing bytes and an under-length cursor. Both must be refused through the normal API error mapping as cursor_expired, HTTP 422 and CLI exit code 2. - Keep unrelated pagination behavior unchanged. ## Acceptance criteria - [ ] A valid cursor with appended bytes is rejected as malformed input before signature verification. - [ ] An under-length cursor is also rejected. - [ ] The consumer-visible error remains cursor_expired, HTTP 422 and exit code 2 through the shared mapper. - [ ] Existing pagination behavior remains unchanged. ## Blocked by None. The check was introduced with the paginated read work in PR 83.
yuris closed this issue 2026-09-23 09:34:32 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
yuris/life-service#91
No description provided.