mirror of
https://github.com/coollabsio/coolify.git
synced 2025-12-28 05:34:50 +00:00
This commit addresses a critical security vulnerability where low-privileged
users (members) could invite high-privileged users (admins/owners) to teams,
allowing them to escalate their own privileges through password reset.
Root Causes Fixed:
1. TeamPolicy authorization checks were commented out, allowing all team
members to manage invitations instead of just admins/owners
2. Missing role elevation checks in InviteLink component allowed members
to invite users with higher privileges
Security Fixes:
1. app/Policies/TeamPolicy.php
- Uncommented and enforced authorization checks for:
* update() - Only admins/owners can update team settings
* delete() - Only admins/owners can delete teams
* manageMembers() - Only admins/owners can manage team members
* viewAdmin() - Only admins/owners can view admin panel
* manageInvitations() - Only admins/owners can manage invitations
2. app/Livewire/Team/InviteLink.php
- Added explicit role elevation checks to prevent:
* Members from inviting admins or owners
* Admins from inviting owners (defense-in-depth)
- Validates that inviter has sufficient privileges for target role
Test Coverage:
1. tests/Feature/TeamPolicyTest.php
- 24 comprehensive tests covering all policy methods
- Tests for owner, admin, member, and non-member access
- Specific tests for the privilege escalation vulnerability
2. tests/Feature/TeamInvitationPrivilegeEscalationTest.php
- 11 tests covering all role elevation scenarios
- Tests member → admin/owner escalation (blocked)
- Tests admin → owner escalation (blocked)
- Tests valid invitation paths for each role
Impact:
- Prevents privilege escalation attacks
- Protects all Coolify instances from unauthorized access
- Enforces proper role hierarchy in team management
References:
- Identified by Aikido AI whitebox pentest service
- CVE: Pending assignment
- Severity: Critical
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
100 lines
2.3 KiB
PHP
100 lines
2.3 KiB
PHP
<?php
|
|
|
|
namespace App\Policies;
|
|
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
|
|
class TeamPolicy
|
|
{
|
|
/**
|
|
* Determine whether the user can view any models.
|
|
*/
|
|
public function viewAny(User $user): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can view the model.
|
|
*/
|
|
public function view(User $user, Team $team): bool
|
|
{
|
|
return $user->teams->contains('id', $team->id);
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can create models.
|
|
*/
|
|
public function create(User $user): bool
|
|
{
|
|
// All authenticated users can create teams
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can update the model.
|
|
*/
|
|
public function update(User $user, Team $team): bool
|
|
{
|
|
// Only admins and owners can update team settings
|
|
if (! $user->teams->contains('id', $team->id)) {
|
|
return false;
|
|
}
|
|
|
|
return $user->isAdmin() || $user->isOwner();
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can delete the model.
|
|
*/
|
|
public function delete(User $user, Team $team): bool
|
|
{
|
|
// Only admins and owners can delete teams
|
|
if (! $user->teams->contains('id', $team->id)) {
|
|
return false;
|
|
}
|
|
|
|
return $user->isAdmin() || $user->isOwner();
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can manage team members.
|
|
*/
|
|
public function manageMembers(User $user, Team $team): bool
|
|
{
|
|
// Only admins and owners can manage team members
|
|
if (! $user->teams->contains('id', $team->id)) {
|
|
return false;
|
|
}
|
|
|
|
return $user->isAdmin() || $user->isOwner();
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can view admin panel.
|
|
*/
|
|
public function viewAdmin(User $user, Team $team): bool
|
|
{
|
|
// Only admins and owners can view admin panel
|
|
if (! $user->teams->contains('id', $team->id)) {
|
|
return false;
|
|
}
|
|
|
|
return $user->isAdmin() || $user->isOwner();
|
|
}
|
|
|
|
/**
|
|
* Determine whether the user can manage invitations.
|
|
*/
|
|
public function manageInvitations(User $user, Team $team): bool
|
|
{
|
|
// Only admins and owners can manage invitations
|
|
if (! $user->teams->contains('id', $team->id)) {
|
|
return false;
|
|
}
|
|
|
|
return $user->isAdmin() || $user->isOwner();
|
|
}
|
|
}
|