The API v1 routes (/api/v1/*) use cookie-based session authentication but explicitly bypass CSRF protection. This means any malicious website can make authenticated requests on behalf of a logged-in user.
Location
internal/server/routes.go — lines in SetupRoutes():
// API v1 routes (cookie-based session auth, no CSRF)s.router.Route("/api/v1",func(rchi.Router){r.With(s.mw.LoginRateLimit()).Post("/login",s.handlers.HandleAPILoginPOST())r.Group(func(rchi.Router){r.Use(s.mw.APISessionAuth())r.Delete("/apps/{id}",s.handlers.HandleAPIDeleteApp())r.Post("/apps/{id}/deploy",s.handlers.HandleAPITriggerDeploy())// ... etc})})
The comment even acknowledges it: cookie-based session auth, no CSRF.
Impact
An attacker can create a webpage that, when visited by a logged-in upaas admin:
Deletes all apps via DELETE /api/v1/apps/{id}
Triggers deployments via POST /api/v1/apps/{id}/deploy
Creates malicious apps via POST /api/v1/apps
Reads app secrets (webhook secrets, SSH keys) via GET /api/v1/apps/{id} (if CORS allows, or via form submission)
This requires only that the victim visits a malicious page while logged in.
Suggested Fix
Either:
Add CSRF tokens to API routes — require X-CSRF-Token header (from a cookie or meta tag)
Switch API to token-based auth — use Authorization: Bearer <token> instead of cookies. This is immune to CSRF since browsers don't auto-attach custom headers.
Require a custom header — e.g., X-Requested-With: XMLHttpRequest. Browsers won't send custom headers in cross-origin simple requests.
Option 2 or 3 is recommended for APIs.
Severity
CRITICAL — Any logged-in admin visiting a malicious page can have their entire PaaS infrastructure destroyed or compromised.
## Summary
The API v1 routes (`/api/v1/*`) use **cookie-based session authentication** but explicitly bypass CSRF protection. This means any malicious website can make authenticated requests on behalf of a logged-in user.
## Location
`internal/server/routes.go` — lines in `SetupRoutes()`:
```go
// API v1 routes (cookie-based session auth, no CSRF)
s.router.Route("/api/v1", func(r chi.Router) {
r.With(s.mw.LoginRateLimit()).Post("/login", s.handlers.HandleAPILoginPOST())
r.Group(func(r chi.Router) {
r.Use(s.mw.APISessionAuth())
r.Delete("/apps/{id}", s.handlers.HandleAPIDeleteApp())
r.Post("/apps/{id}/deploy", s.handlers.HandleAPITriggerDeploy())
// ... etc
})
})
```
The comment even acknowledges it: `cookie-based session auth, no CSRF`.
## Impact
An attacker can create a webpage that, when visited by a logged-in upaas admin:
1. **Deletes all apps** via `DELETE /api/v1/apps/{id}`
2. **Triggers deployments** via `POST /api/v1/apps/{id}/deploy`
3. **Creates malicious apps** via `POST /api/v1/apps`
4. **Reads app secrets** (webhook secrets, SSH keys) via `GET /api/v1/apps/{id}` (if CORS allows, or via form submission)
This requires only that the victim visits a malicious page while logged in.
## Suggested Fix
Either:
1. **Add CSRF tokens to API routes** — require `X-CSRF-Token` header (from a cookie or meta tag)
2. **Switch API to token-based auth** — use `Authorization: Bearer <token>` instead of cookies. This is immune to CSRF since browsers don't auto-attach custom headers.
3. **Require a custom header** — e.g., `X-Requested-With: XMLHttpRequest`. Browsers won't send custom headers in cross-origin simple requests.
Option 2 or 3 is recommended for APIs.
## Severity
**CRITICAL** — Any logged-in admin visiting a malicious page can have their entire PaaS infrastructure destroyed or compromised.
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.
Summary
The API v1 routes (
/api/v1/*) use cookie-based session authentication but explicitly bypass CSRF protection. This means any malicious website can make authenticated requests on behalf of a logged-in user.Location
internal/server/routes.go— lines inSetupRoutes():The comment even acknowledges it:
cookie-based session auth, no CSRF.Impact
An attacker can create a webpage that, when visited by a logged-in upaas admin:
DELETE /api/v1/apps/{id}POST /api/v1/apps/{id}/deployPOST /api/v1/appsGET /api/v1/apps/{id}(if CORS allows, or via form submission)This requires only that the victim visits a malicious page while logged in.
Suggested Fix
Either:
X-CSRF-Tokenheader (from a cookie or meta tag)Authorization: Bearer <token>instead of cookies. This is immune to CSRF since browsers don't auto-attach custom headers.X-Requested-With: XMLHttpRequest. Browsers won't send custom headers in cross-origin simple requests.Option 2 or 3 is recommended for APIs.
Severity
CRITICAL — Any logged-in admin visiting a malicious page can have their entire PaaS infrastructure destroyed or compromised.
disable the api’s write methods.