mirror of
https://github.com/coollabsio/coolify.git
synced 2026-09-27 17:55:59 -04:00
fix(env): prevent copying unauthorized and shown-once values
Lock compose variable lookup fields against client changes, check resource update permission before resolving references, and exclude shown-once variables from reference lookup.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
||||
|
||||
use App\Models\EnvironmentVariable;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Component;
|
||||
|
||||
class ShowHardcoded extends Component
|
||||
@@ -13,16 +14,20 @@ class ShowHardcoded extends Component
|
||||
|
||||
public string $key;
|
||||
|
||||
#[Locked]
|
||||
public ?string $value = null;
|
||||
|
||||
public ?string $comment = null;
|
||||
|
||||
public ?string $serviceName = null;
|
||||
|
||||
#[Locked]
|
||||
public bool $isPreview = false;
|
||||
|
||||
#[Locked]
|
||||
public ?string $resourceableType = null;
|
||||
|
||||
#[Locked]
|
||||
public ?int $resourceableId = null;
|
||||
|
||||
public function mount()
|
||||
@@ -39,12 +44,19 @@ class ShowHardcoded extends Component
|
||||
return null;
|
||||
}
|
||||
|
||||
return EnvironmentVariable::make([
|
||||
$environmentVariable = EnvironmentVariable::make([
|
||||
'value' => $this->value,
|
||||
'is_preview' => $this->isPreview,
|
||||
'resourceable_type' => $this->resourceableType,
|
||||
'resourceable_id' => $this->resourceableId,
|
||||
])->resolveReferencedValue();
|
||||
]);
|
||||
$resource = $environmentVariable->resourceable;
|
||||
|
||||
if (! $resource || auth()->user()->cannot('update', $resource)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $environmentVariable->resolveReferencedValue();
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -346,6 +346,7 @@ class EnvironmentVariable extends BaseModel
|
||||
return static::where('resourceable_type', $this->resourceable_type)
|
||||
->where('resourceable_id', $this->resourceable_id)
|
||||
->where('is_preview', (bool) $this->is_preview)
|
||||
->where('is_shown_once', false)
|
||||
->where('key', $referencedKey)
|
||||
->first()?->value ?? $value;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ use App\Models\Environment;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Project;
|
||||
use App\Models\Service;
|
||||
use App\Models\SharedEnvironmentVariable;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException;
|
||||
use Livewire\Livewire;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
@@ -135,6 +137,49 @@ test('compose-managed rows copy the referenced variable value', function () {
|
||||
assertCopiedComposeValue('production', 'production');
|
||||
});
|
||||
|
||||
test('copying a reference does not reveal a locked variable', function () {
|
||||
createEnvironmentVariable(['key' => 'SERVICE_PASSWORD_MYSQL', 'value' => 'locked-password', 'is_shown_once' => true]);
|
||||
|
||||
assertCopiedValue(
|
||||
createEnvironmentVariable(['key' => 'DB_PASSWORD', 'value' => '$SERVICE_PASSWORD_MYSQL']),
|
||||
'$SERVICE_PASSWORD_MYSQL',
|
||||
);
|
||||
assertCopiedComposeValue('$SERVICE_PASSWORD_MYSQL', '$SERVICE_PASSWORD_MYSQL');
|
||||
});
|
||||
|
||||
test('compose-managed rows do not accept a changed lookup from the client', function (string $property, mixed $value) {
|
||||
Livewire::test(ShowHardcoded::class, [
|
||||
'env' => ['key' => 'MYSQL_USER', 'value' => 'production'],
|
||||
'resourceableType' => Application::class,
|
||||
'resourceableId' => test()->application->id,
|
||||
])->set($property, $value);
|
||||
})->with([
|
||||
'value' => ['value', '$DATABASE_PASSWORD'],
|
||||
'preview scope' => ['isPreview', true],
|
||||
'resource type' => ['resourceableType', Service::class],
|
||||
'resource id' => ['resourceableId', 999],
|
||||
])->throws(CannotUpdateLockedPropertyException::class);
|
||||
|
||||
test('compose-managed rows do not copy values from another team', function () {
|
||||
$otherTeam = Team::factory()->create();
|
||||
$otherProject = Project::factory()->create(['team_id' => $otherTeam->id]);
|
||||
$otherEnvironment = Environment::factory()->create(['project_id' => $otherProject->id]);
|
||||
$otherApplication = Application::factory()->create(['environment_id' => $otherEnvironment->id]);
|
||||
createEnvironmentVariable([
|
||||
'key' => 'DATABASE_PASSWORD',
|
||||
'value' => 'other-team-secret',
|
||||
'resourceable_id' => $otherApplication->id,
|
||||
]);
|
||||
|
||||
Livewire::test(ShowHardcoded::class, [
|
||||
'env' => ['key' => 'DB_PASSWORD', 'value' => '$DATABASE_PASSWORD'],
|
||||
'resourceableType' => Application::class,
|
||||
'resourceableId' => $otherApplication->id,
|
||||
])
|
||||
->call('copyValue')
|
||||
->assertReturned(null);
|
||||
});
|
||||
|
||||
test('compose-managed rows hide copying from members', function () {
|
||||
$member = User::factory()->create();
|
||||
$this->team->members()->attach($member, ['role' => 'member']);
|
||||
|
||||
Reference in New Issue
Block a user