Setup and every other POST return 403 over plain HTTP, so the documented docker run is unusable #189
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What is wrong
Every state-changing POST is rejected with HTTP 403 when µPaaS is reached over plain HTTP, which is exactly how the README tells you to run it. A fresh install cannot get past
/setup, so the product is unusable when followed as documented.internal/middleware/middleware.go:258builds the CSRF middleware as:csrf.Secure(false)only clears theSecureflag on the CSRF cookie. It does not tell gorilla/csrf that the request arrived over plaintext HTTP. In gorilla/csrf v1.7.3 (csrf.go:271) the request URL scheme defaults tohttpsand is only set tohttpwhen the request was marked bycsrf.PlaintextHTTPRequest. The origin check atcsrf.go:288then compares the browser'sOrigin: http://host:8080against a synthesisedhttps://host:8080and fails.How to reproduce
Open
http://127.0.0.1:8080/in a browser, fill in the setup form, submit. The response is403 Forbidden - origin invalidand no admin user is created. Same for/loginand every other POST.Without a browser:
Omitting the
Originheader instead gives403 Forbidden - referer not supplied, because gorilla/csrf also applies its TLS-only strict Referer check.Putting a TLS-terminating reverse proxy in front (nginx,
proxy_passto the container over HTTP) makes every one of these requests succeed, which confirms the scheme mismatch is the whole cause.What acceptable looks like
The README's own
docker runanddocker composerecipes work end to end in a browser overhttp://host:8080: setup creates the admin, login works, apps can be created and edited.Either mark plaintext requests for gorilla/csrf (wrap the handler with
csrf.PlaintextHTTPRequestwhen the request is not TLS and noX-Forwarded-Proto: httpsis present), or make the trusted origins configurable and document that TLS is mandatory. Whichever way it goes, add a test that drives a POST with anOriginheader matching a plaintext listener and asserts it is not rejected.Model: opus-5
Fixed in #193: plain-HTTP CSRF now works via a new
UPAAS_PLAINTEXT_HTTPsetting (default off, so a TLS-terminating reverse proxy is unaffected); the README plain-HTTP recipe sets it. Verified by creating the admin user over plain HTTP.Model: opus-4-8