Firefly III user API endpoints expose all users' information to any authenticated user (IDOR)
Key facts
- Attack vector
- —
- Privileges required
- —
- User interaction
- —
- Attack complexity
- —
- Impact type
- Security bypass
- Confidentiality · integrity · availability
- —
- Fix status
- Fixed
No CVSS vector from any source. Fix status from GitHub. Impact type from CWE-863.
Summary
### Summary The User management API endpoints (`GET /api/v1/users` and `GET /api/v1/users/{id}`) are accessible to any authenticated user without admin/owner role verification, exposing all users' email addresses, roles, and account status. ### Affected Endpoints 1. **GET /api/v1/users** (UserController::index, line 94) — Lists ALL users with full details. No role check. 2. **GET /api/v1/users/{id}** (UserController::show, line 126) — Shows any user's details by ID. No role check. ### Root Cause (1-of-N Inconsistency) Other methods in the same controller properly check for the 'owner' role: - `store()` — `UserStoreRequest::authorize()` checks `auth()->user()->hasRole('owner')` ✓ - `destroy()` — Explicitly checks `$this->repository->hasRole($admin, 'owner')` ✓ But `index()` and `show()` have no role check at all. The route group at `routes/api.php:734-747` has no admin middleware, only the global `auth:api` middleware. ### Exposed Data The `UserTransformer` (line 40-54) returns: - `email` — user's email address - `role` — user's role (owner/demo) - `blocked` — account blocked status - `blocked_code` — block reason - `created_at` / `updated_at` — timestamps ### Impact Any authenticated user can: 1. Enumerate ALL user accounts in the instance 2. Harvest email addresses for phishing/social engineering 3. Identify admin/owner accounts by role 4. Determine which accounts are blocked ### Exploitation ```bash # List all users curl -H "Authorization: Bearer <any_user_token>" https://instance/api/v1/users # View specific user details curl -H "Authorization: Bearer <any_user_token>" https://instance/api/v1/users/1 ``` ### Suggested Fix Add owner role checks to `index()` and `show()`, or restrict the route group with admin middleware: ```php // Option 1: Add check in controller methods public function show(User $user): JsonResponse { if (!$this->repository->hasRole(auth()->user(), 'owner') && auth()->user()->id !== $user->id) { throw new FireflyException('200025: No access to function.'); } // ... } // Option 2: Add middleware to route group Route::group(['middleware' => ['admin'], ...], ...) ```
Why it matters now
SSVC decision points
Not available: CISA has not published SSVC decision points for this record.
Affected products
| Vendor | Product | Affected versions | Fixed in | Status | Source |
|---|---|---|---|---|---|
| — | grumpydictator/firefly-iii (Packagist) | 6.4.23 to before 6.5.1 | 6.5.1 | Patch available | GHSA-5q8v-j673-m5v4 |
- grumpydictator/firefly-iii (Packagist) Vendor— Affected 6.4.23 to before 6.5.1 Fixed in 6.5.1 Patch available GHSA-5q8v-j673-m5v4
Remediation
- Fix · GHSA-5q8v-j673-m5v4 grumpydictator/firefly-iii (Packagist) Fixed in 6.5.1 Advisory →
Timeline
- 2026-10-03 Threatist record created from GHSA-5q8v-j673-m5v4
References
Sources
This product uses the NVD API but is not endorsed or certified by the NVD. Sources and licences