The deletion token was accepted via the ?token= query parameter on both DELETE /api/pastes/{id} and /api/pastes/{id}/redeem, and the UI round-tripped it through the paste URL after creation. URL-carried bearer secrets end up in Traefik access logs and browser history.
Fix
API: deletion token accepted only via the Authorization header (Bearer/Token/bare); query params ignored on both delete and redeem
Create flow: token handed to the browser as a short-lived (60s) HttpOnly tok_<id> cookie instead of the redirect URL; the paste view reads it from the cookie, never from ?token=
Paste view: the delete button reads the token from sessionStorage (populated from the create response) and sends it as an Authorization header
Old links carrying ?token= simply lose the delete button (token no longer honored); paste viewing is unaffected
Verification
go build ./... and go test ./... pass
New/updated tests: correct token in query now returns 403 (delete) / 400 (redeem) and the paste survives; Authorization header path still deletes and redeems; deletionAuthorization unit cases updated
Ran the binary locally and hit the endpoints: redeem ?token= -> 400, delete ?token= -> 403, header redeem -> 200, paste gone; a legacy URL with the real token renders no token and no cookie
Fixes #143.
The deletion token was accepted via the `?token=` query parameter on both DELETE `/api/pastes/{id}` and `/api/pastes/{id}/redeem`, and the UI round-tripped it through the paste URL after creation. URL-carried bearer secrets end up in Traefik access logs and browser history.
## Fix
- API: deletion token accepted only via the Authorization header (Bearer/Token/bare); query params ignored on both delete and redeem
- Create flow: token handed to the browser as a short-lived (60s) HttpOnly `tok_<id>` cookie instead of the redirect URL; the paste view reads it from the cookie, never from `?token=`
- Paste view: the delete button reads the token from sessionStorage (populated from the create response) and sends it as an Authorization header
- Old links carrying `?token=` simply lose the delete button (token no longer honored); paste viewing is unaffected
## Verification
- `go build ./...` and `go test ./...` pass
- New/updated tests: correct token in query now returns 403 (delete) / 400 (redeem) and the paste survives; Authorization header path still deletes and redeems; `deletionAuthorization` unit cases updated
- Ran the binary locally and hit the endpoints: redeem `?token=` -> 400, delete `?token=` -> 403, header redeem -> 200, paste gone; a legacy URL with the real token renders no token and no cookie
The deletion token was accepted via the ?token= query parameter on both
DELETE /api/pastes/{id} and /redeem, and round-tripped through the paste
URL after creation. URL-carried bearer secrets leak into reverse-proxy
access logs and browser history.
- API: deletion tokens are now accepted only via the Authorization header
(Bearer/Token/bare); query params are ignored on both endpoints
- Web create flow: token moves to the browser via a short-lived tok_<id>
HttpOnly cookie instead of the redirect URL; the paste view reads it
from the cookie, never from ?token=
- Web view: the delete button calls redeem() which takes the token from
sessionStorage and sends it as an Authorization header
- Tests: correct token in query must be rejected (403/400); header path
still deletes/redeems; extraction unit cases updated
Fixes#143
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #143.
The deletion token was accepted via the
?token=query parameter on both DELETE/api/pastes/{id}and/api/pastes/{id}/redeem, and the UI round-tripped it through the paste URL after creation. URL-carried bearer secrets end up in Traefik access logs and browser history.Fix
tok_<id>cookie instead of the redirect URL; the paste view reads it from the cookie, never from?token=?token=simply lose the delete button (token no longer honored); paste viewing is unaffectedVerification
go build ./...andgo test ./...passdeletionAuthorizationunit cases updated?token=-> 400, delete?token=-> 403, header redeem -> 200, paste gone; a legacy URL with the real token renders no token and no cookieThe deletion token was accepted via the ?token= query parameter on both DELETE /api/pastes/{id} and /redeem, and round-tripped through the paste URL after creation. URL-carried bearer secrets leak into reverse-proxy access logs and browser history. - API: deletion tokens are now accepted only via the Authorization header (Bearer/Token/bare); query params are ignored on both endpoints - Web create flow: token moves to the browser via a short-lived tok_<id> HttpOnly cookie instead of the redirect URL; the paste view reads it from the cookie, never from ?token= - Web view: the delete button calls redeem() which takes the token from sessionStorage and sends it as an Authorization header - Tests: correct token in query must be rejected (403/400); header path still deletes/redeems; extraction unit cases updated Fixes #1436d17de6ff0to00aaafeb3c