audit the whole app for stupid cases of missing functionality or basic things like this (like the stats panel at the top that i requested).
What is wrong: a signed-out operator who opens any admin page is sent to sign-in, and afterwards always lands on the webhook list, not on the page they asked for. That happens with a bookmarked event log, a link shared in chat, or a session that ended after SESSION_IDLE_TIMEOUT. In the audit, opening a webhook's event log while signed out and then signing in landed on /sources.
RequireAuth in internal/middleware/middleware.go redirects to /pages/login and keeps nothing of the original request, and HandleLoginSubmit in internal/handlers/auth.go always redirects to /. The sign-in page also shows a "Login" button in the navigation bar that links to the page it is already on (templates/navbar.html).
Definition of done:
After a redirect to sign-in from a GET request, signing in lands on the page originally asked for, path and query included.
Only a path on this site is accepted as that destination. An absolute URL, a //host value or anything else falls back to the webhook list, so the parameter cannot send anyone elsewhere.
Signing in without such a redirect lands on the webhook list, as today.
The navigation bar on the sign-in page has no link to the sign-in page.
Tests: a deep link through sign-in lands on that link, and an off-site or //host destination is ignored.
PRIORITY: from the owner's audit request of 1 October (#377), in the tier of #367 to #376.
Model: opus-5-5
Owner's request, https://git.eeqj.de/sneak/webhooker/issues/377 (chat, 2026-10-01):
> audit the whole app for stupid cases of missing functionality or basic things like this (like the stats panel at the top that i requested).
What is wrong: a signed-out operator who opens any admin page is sent to sign-in, and afterwards always lands on the webhook list, not on the page they asked for. That happens with a bookmarked event log, a link shared in chat, or a session that ended after `SESSION_IDLE_TIMEOUT`. In the audit, opening a webhook's event log while signed out and then signing in landed on `/sources`.
`RequireAuth` in `internal/middleware/middleware.go` redirects to `/pages/login` and keeps nothing of the original request, and `HandleLoginSubmit` in `internal/handlers/auth.go` always redirects to `/`. The sign-in page also shows a "Login" button in the navigation bar that links to the page it is already on (`templates/navbar.html`).
Definition of done:
- After a redirect to sign-in from a GET request, signing in lands on the page originally asked for, path and query included.
- Only a path on this site is accepted as that destination. An absolute URL, a `//host` value or anything else falls back to the webhook list, so the parameter cannot send anyone elsewhere.
- Signing in without such a redirect lands on the webhook list, as today.
- The navigation bar on the sign-in page has no link to the sign-in page.
- Tests: a deep link through sign-in lands on that link, and an off-site or `//host` destination is ignored.
PRIORITY: from the owner's audit request of 1 October (https://git.eeqj.de/sneak/webhooker/issues/377), in the tier of https://git.eeqj.de/sneak/webhooker/issues/367 to https://git.eeqj.de/sneak/webhooker/issues/376.
Model: opus-5-5
clawbot
self-assigned this 2026-10-01 22:06:18 +02:00
Plan. The issue body is the brief. RequireAuth adds the requested path and query to the sign-in redirect as a parameter, for GET requests only; the sign-in form carries it as a hidden field; after a successful sign-in the handler redirects there only when the value is a path on this site (one leading /, not // or /\), and to the webhook list otherwise. The navigation bar on the sign-in page drops its sign-in link. It rebases onto #378's paths if that lands first.
Model: opus-5-5
Plan. The issue body is the brief. `RequireAuth` adds the requested path and query to the sign-in redirect as a parameter, for GET requests only; the sign-in form carries it as a hidden field; after a successful sign-in the handler redirects there only when the value is a path on this site (one leading `/`, not `//` or `/\`), and to the webhook list otherwise. The navigation bar on the sign-in page drops its sign-in link. It rebases onto https://git.eeqj.de/sneak/webhooker/pulls/378's paths if that lands first.
Model: opus-5-5
Built in #406. A logged-out GET of an admin page now carries its path and query to the login page as next, and logging in returns there. Only a path on this site is followed, checked after percent-decoding; an absolute URL, //host, /\host, their encoded forms, a control character or an empty value lands on the webhook list. The login page's navigation bar no longer links to itself.
Rule suppressed: gosec G710 (open redirect) on the two redirects that follow next, since its taint tracking cannot see the check.
Judgement call: a next longer than 2048 bytes falls back to the webhook list, since the login page writes it into its form.
Judgement call: an already logged-in visit to the login page also follows next.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/webhooker/pulls/406. A logged-out `GET` of an admin page now carries its path and query to the login page as `next`, and logging in returns there. Only a path on this site is followed, checked after percent-decoding; an absolute URL, `//host`, `/\host`, their encoded forms, a control character or an empty value lands on the webhook list. The login page's navigation bar no longer links to itself.
- Rule suppressed: gosec G710 (open redirect) on the two redirects that follow `next`, since its taint tracking cannot see the check.
- Judgement call: a `next` longer than 2048 bytes falls back to the webhook list, since the login page writes it into its form.
- Judgement call: an already logged-in visit to the login page also follows `next`.
Model: opus-5-5
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.
Owner's request, #377 (chat, 2026-10-01):
What is wrong: a signed-out operator who opens any admin page is sent to sign-in, and afterwards always lands on the webhook list, not on the page they asked for. That happens with a bookmarked event log, a link shared in chat, or a session that ended after
SESSION_IDLE_TIMEOUT. In the audit, opening a webhook's event log while signed out and then signing in landed on/sources.RequireAuthininternal/middleware/middleware.goredirects to/pages/loginand keeps nothing of the original request, andHandleLoginSubmitininternal/handlers/auth.goalways redirects to/. The sign-in page also shows a "Login" button in the navigation bar that links to the page it is already on (templates/navbar.html).Definition of done:
//hostvalue or anything else falls back to the webhook list, so the parameter cannot send anyone elsewhere.//hostdestination is ignored.PRIORITY: from the owner's audit request of 1 October (#377), in the tier of #367 to #376.
Model: opus-5-5
Plan. The issue body is the brief.
RequireAuthadds the requested path and query to the sign-in redirect as a parameter, for GET requests only; the sign-in form carries it as a hidden field; after a successful sign-in the handler redirects there only when the value is a path on this site (one leading/, not//or/\), and to the webhook list otherwise. The navigation bar on the sign-in page drops its sign-in link. It rebases onto #378's paths if that lands first.Model: opus-5-5
Built in #406. A logged-out
GETof an admin page now carries its path and query to the login page asnext, and logging in returns there. Only a path on this site is followed, checked after percent-decoding; an absolute URL,//host,/\host, their encoded forms, a control character or an empty value lands on the webhook list. The login page's navigation bar no longer links to itself.next, since its taint tracking cannot see the check.nextlonger than 2048 bytes falls back to the webhook list, since the login page writes it into its form.next.Model: opus-5-5