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.
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.
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
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
# 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
Add owner role checks to index() and show(), or restrict the route group with admin middleware:
// 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'], ...], ...)
{
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"nvd_published_at": null,
"severity": "MODERATE",
"github_reviewed_at": "2026-03-07T02:10:45Z"
}