T09 · Insecure Skill Coding Practices
- Location
references/pagination.md:129- Finding
Unsigned Base64 Pagination Cursors Are Client-Tamperable
- Content
View full analysis
Vulnerability Details
File Location:
references/pagination.md, lines 129–132 and 157
Vulnerability Type: Unsigned and tamperable pagination cursor
Risk Level: MediumVulnerable Code Snippet:
markdown **Cursor structure (base64 encoded):** ```json {"id": 30, "sort": "created_at"}text The same document later makes the following unsafe assumption: ```markdown - Cursor is opaque (users can't modify it)Technical Analysis
The guidance recommends encoding cursor state as Base64 and incorrectly implies that users cannot modify it. Base64 only transforms data into another representation; it provides no confidentiality, authenticity, or integrity protection.
A client can decode the cursor, modify fields such as the record identifier, timestamp, or sorting state, and then re-encode it. If an API implementation trusts those values without cryptographic verification and strict server-side validation, the attacker can manipulate pagination boundaries.
The risk becomes more significant if a cursor contains tenant identifiers, authorization scope, filters, or other security-relevant state. Authorization must never depend solely on untrusted cursor contents.
Attack Path
- An attacker makes a legitimate collection request and receives a Base64-encoded cursor.
- The attacker Base64-decodes the cursor and obtains its JSON payload.
- The attacker changes fields such as
id,created_at, sorting state, filters, or scope identifiers. - The attacker Base64-encodes the altered payload.
- The modified cursor is submitted to the API.
- If the server trusts the decoded cursor without checking its integrity, the manipulated state controls the subsequent database query.
- Depending on the implementation, this may expose records outside intended pagination boundaries or bypass enforced filter state.
Impact Assessment
Successful exploitation may allow an unauthenticated or ordinarily authenticated API client to manipulate pagin ...[truncated 598 chars]
- Remediation
View remediation
Remediation Suggestions
- Protect cursor integrity using an HMAC with a server-held secret, or use authenticated encryption such as AES-GCM when cursor confidentiality is also required.
- Verify the signature before decoding or using cursor-controlled state. Reject unsigned cursors and cursors with invalid signatures.
- Bind each cursor to the authenticated user or tenant, original filter set, sort order, page-size constraints, and an expiration time.
- Validate the decoded payload against a strict schema, including allowed fields, types, ranges, and sort-field allowlists.
- Use parameterized database queries and never concatenate cursor values into SQL.
- Reapply authorization and tenant restrictions independently on every paginated request. Do not rely on authorization scope stored in the cursor.
- Return a generic invalid-cursor response without revealing signing, parsing, database, or internal implementation details.
- Replace the unsafe statement with guidance explaining that Base64 provides opacity only and does not prevent modification.
