Original flaw
Earlier flawThe permission-save endpoint accepted unauthenticated role-permission mutations.
Sink: Prospero PermissionSaveController POST /permission and syncPermissions
Originally written by a human commit
Loading…
How AI contributed
Incomplete remediationMissing Authorization in the permission management component in Roskus Prospero Flow CRM before 5.2.1 allows any authenticated user to grant any role, including their own, the complete set of application permissions via a crafted POST request to the permission save endpoint, which performs no authorization check before synchronizing the submitted permissions to the specified role.
Only the highlighted steps are this advisory. The first card is the earlier flaw the AI tried, and failed, to close.
Original flaw
Earlier flawSink: Prospero PermissionSaveController POST /permission and syncPermissions
Originally written by a human commit
This advisoryCVE-2026-59233 (GHSA-4FXP-2M36-QV64)
AI tried to fix this
The AI change was a real security patch, but it left the same advisory reachable.
Missed: Added no authorization check for the submitted target role and permissions.
Incomplete AI fix · Claude
Fixed again
This is the patch that actually stops the same attack path.
AI-assisted fix: Claude Code · Gustavo Novaro
Code comparison
--- a/app/Http/Controllers/Permission/PermissionSaveController.php+++ b/app/Http/Controllers/Permission/PermissionSaveController.php@@ -5,20 +5,21 @@ declare(strict_types=1); namespace App\Http\Controllers\Permission; use App\Http\Controllers\MainController;+use App\Http\Requests\PermissionSaveRequest; use Illuminate\Http\RedirectResponse;-use Illuminate\Http\Request; use Spatie\Permission\Models\Role; class PermissionSaveController extends MainController {- public function save(Request $request): RedirectResponse+ public function save(PermissionSaveRequest $request): RedirectResponse {- $roles = $request->roles;-- foreach ($roles as $role_id => $permissions) {- Role::findById($role_id)->syncPermissions($permissions);+ foreach ($request->validated()['roles'] as $role_id => $permissions) {+ $role = Role::find($role_id);+ if ($role) {+ $role->syncPermissions($permissions);+ } } - return redirect('/permission');+ return redirect('/permission')->with('success', __('Permissions updated successfully')); } }Candidate e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 · Fix f315a3d8ac6b675d84d7f0e73a772c23ec24406d3ecd38846c4eeedc4590fedc
Releases
Advisory references