fix(api): extract resource UUIDs from route parameters
Extract resource UUIDs from route parameters instead of request body
in ApplicationsController and ServicesController environment variable
endpoints. This prevents UUID parameters from being spoofed in the
request body.
- Replace $request->uuid with $request->route('uuid')
- Replace $request->env_uuid with $request->route('env_uuid')
- Add tests verifying route parameters are used and body UUIDs ignored
This commit is contained in:
parent
d0b4dc1c63
commit
8a164735cb
3 changed files with 71 additions and 11 deletions
|
|
@ -2957,7 +2957,7 @@ public function update_env_by_uuid(Request $request)
|
|||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
return $return;
|
||||
}
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->route('uuid'))->first();
|
||||
|
||||
if (! $application) {
|
||||
return response()->json([
|
||||
|
|
@ -3158,7 +3158,7 @@ public function create_bulk_envs(Request $request)
|
|||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
return $return;
|
||||
}
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->route('uuid'))->first();
|
||||
|
||||
if (! $application) {
|
||||
return response()->json([
|
||||
|
|
@ -3352,7 +3352,7 @@ public function create_env(Request $request)
|
|||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->route('uuid'))->first();
|
||||
|
||||
if (! $application) {
|
||||
return response()->json([
|
||||
|
|
@ -3509,7 +3509,7 @@ public function delete_env_by_uuid(Request $request)
|
|||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
|
||||
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->route('uuid'))->first();
|
||||
|
||||
if (! $application) {
|
||||
return response()->json([
|
||||
|
|
@ -3519,7 +3519,7 @@ public function delete_env_by_uuid(Request $request)
|
|||
|
||||
$this->authorize('manageEnvironment', $application);
|
||||
|
||||
$found_env = EnvironmentVariable::where('uuid', $request->env_uuid)
|
||||
$found_env = EnvironmentVariable::where('uuid', $request->route('env_uuid'))
|
||||
->where('resourceable_type', Application::class)
|
||||
->where('resourceable_id', $application->id)
|
||||
->first();
|
||||
|
|
|
|||
|
|
@ -1207,7 +1207,7 @@ public function update_env_by_uuid(Request $request)
|
|||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->route('uuid'))->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
|
@ -1342,7 +1342,7 @@ public function create_bulk_envs(Request $request)
|
|||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->route('uuid'))->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
|
@ -1461,7 +1461,7 @@ public function create_env(Request $request)
|
|||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->route('uuid'))->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
|
@ -1570,14 +1570,14 @@ public function delete_env_by_uuid(Request $request)
|
|||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->route('uuid'))->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
||||
$this->authorize('manageEnvironment', $service);
|
||||
|
||||
$env = EnvironmentVariable::where('uuid', $request->env_uuid)
|
||||
$env = EnvironmentVariable::where('uuid', $request->route('env_uuid'))
|
||||
->where('resourceable_type', Service::class)
|
||||
->where('resourceable_id', $service->id)
|
||||
->first();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use App\Models\Application;
|
||||
use App\Models\Environment;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
|
|
@ -14,6 +15,8 @@
|
|||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
InstanceSettings::updateOrCreate(['id' => 0]);
|
||||
|
||||
$this->team = Team::factory()->create();
|
||||
$this->user = User::factory()->create();
|
||||
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
|
||||
|
|
@ -24,7 +27,7 @@
|
|||
$this->bearerToken = $this->token->plainTextToken;
|
||||
|
||||
$this->server = Server::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->destination = StandaloneDocker::factory()->create(['server_id' => $this->server->id]);
|
||||
$this->destination = StandaloneDocker::where('server_id', $this->server->id)->first();
|
||||
$this->project = Project::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||
});
|
||||
|
|
@ -117,6 +120,35 @@
|
|||
|
||||
$response->assertStatus(422);
|
||||
});
|
||||
|
||||
test('uses route uuid and ignores uuid in request body', function () {
|
||||
$service = Service::factory()->create([
|
||||
'server_id' => $this->server->id,
|
||||
'destination_id' => $this->destination->id,
|
||||
'destination_type' => $this->destination->getMorphClass(),
|
||||
'environment_id' => $this->environment->id,
|
||||
]);
|
||||
|
||||
EnvironmentVariable::create([
|
||||
'key' => 'TEST_KEY',
|
||||
'value' => 'old-value',
|
||||
'resourceable_type' => Service::class,
|
||||
'resourceable_id' => $service->id,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'Authorization' => 'Bearer '.$this->bearerToken,
|
||||
'Content-Type' => 'application/json',
|
||||
])->patchJson("/api/v1/services/{$service->uuid}/envs", [
|
||||
'key' => 'TEST_KEY',
|
||||
'value' => 'new-value',
|
||||
'uuid' => 'bogus-uuid-from-body',
|
||||
]);
|
||||
|
||||
$response->assertStatus(201);
|
||||
$response->assertJsonFragment(['key' => 'TEST_KEY']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('PATCH /api/v1/applications/{uuid}/envs', function () {
|
||||
|
|
@ -191,4 +223,32 @@
|
|||
|
||||
$response->assertStatus(422);
|
||||
});
|
||||
|
||||
test('rejects unknown fields in request body', function () {
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $this->environment->id,
|
||||
'destination_id' => $this->destination->id,
|
||||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
EnvironmentVariable::create([
|
||||
'key' => 'TEST_KEY',
|
||||
'value' => 'old-value',
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'Authorization' => 'Bearer '.$this->bearerToken,
|
||||
'Content-Type' => 'application/json',
|
||||
])->patchJson("/api/v1/applications/{$application->uuid}/envs", [
|
||||
'key' => 'TEST_KEY',
|
||||
'value' => 'new-value',
|
||||
'uuid' => 'bogus-uuid-from-body',
|
||||
]);
|
||||
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonFragment(['uuid' => ['This field is not allowed.']]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue