Skip to content

Commit c332151

Browse files
committed
Merge branch 'release/v1.11.7' of https://github.com/pterodactyl/panel into release/v1.11.5
2 parents 235e100 + 62b8a53 commit c332151

File tree

29 files changed

+197
-236
lines changed

29 files changed

+197
-236
lines changed

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,32 @@ This file is a running track of new features and fixes to each version of the pa
33

44
This project follows [Semantic Versioning](http://semver.org) guidelines.
55

6+
## v1.11.7
7+
8+
### Added
9+
10+
* Java 21 to Minecraft eggs
11+
12+
### Changed
13+
14+
* Updated Minecraft EULA link
15+
16+
### Fixed
17+
18+
* Fixed backups not ever being marked as completed (#5088)
19+
* Fixed `.7z` files not being detected as a compressed file (#5016)
20+
21+
## v1.11.6
22+
23+
### Changed
24+
25+
* Better node ownership checks for internal backup endpoints
26+
* Improved validation rules on `docker_image` fields to prevent invalid inputs
27+
28+
### Fixed
29+
30+
* Multiple XSS vulnerabilities in the admin area ([GHSA-384w-wffr-x63q](https://github.com/pterodactyl/panel/security/advisories/GHSA-384w-wffr-x63q))
31+
632
## v1.11.5
733
### Fixed
834
* Rust egg using the wrong Docker image, breaking Rust modding frameworks.

SECURITY.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ The following versions of Pterodactyl are receiving active support and maintenan
66

77
| Panel | Daemon | Supported |
88
|--------|--------------|--------------------|
9-
| 1.10.x | [email protected] | :white_check_mark: |
109
| 1.11.x | [email protected] | :white_check_mark: |
1110
| 0.7.x | [email protected] | :x: |
1211

app/Http/Controllers/Admin/Nests/EggVariableController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function update(EggVariableFormRequest $request, Egg $egg, EggVariable $v
6969
{
7070
$this->updateService->handle($variable, $request->normalize());
7171
$this->alert->success(trans('admin/nests.variables.notices.variable_updated', [
72-
'variable' => $variable->name,
72+
'variable' => htmlspecialchars($variable->name),
7373
]))->flash();
7474

7575
return redirect()->route('admin.nests.egg.variables', $egg->id);
@@ -82,7 +82,7 @@ public function destroy(int $egg, EggVariable $variable): RedirectResponse
8282
{
8383
$this->variableRepository->delete($variable->id);
8484
$this->alert->success(trans('admin/nests.variables.notices.variable_deleted', [
85-
'variable' => $variable->name,
85+
'variable' => htmlspecialchars($variable->name),
8686
]))->flash();
8787

8888
return redirect()->route('admin.nests.egg.variables', $egg);

app/Http/Controllers/Admin/Nests/NestController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function create(): View
5656
public function store(StoreNestFormRequest $request): RedirectResponse
5757
{
5858
$nest = $this->nestCreationService->handle($request->normalize());
59-
$this->alert->success(trans('admin/nests.notices.created', ['name' => $nest->name]))->flash();
59+
$this->alert->success(trans('admin/nests.notices.created', ['name' => htmlspecialchars($nest->name)]))->flash();
6060

6161
return redirect()->route('admin.nests.view', $nest->id);
6262
}

app/Http/Controllers/Admin/NodesController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public function allocationRemoveBlock(Request $request, int $node): RedirectResp
131131
['ip', '=', $request->input('ip')],
132132
]);
133133

134-
$this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => $request->input('ip')]))
134+
$this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => htmlspecialchars($request->input('ip'))]))
135135
->flash();
136136

137137
return redirect()->route('admin.nodes.view.allocation', $node);

app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,32 @@ public function __construct(private BackupManager $backupManager)
3232
*/
3333
public function __invoke(Request $request, string $backup): JsonResponse
3434
{
35+
// Get the node associated with the request.
36+
/** @var \Pterodactyl\Models\Node $node */
37+
$node = $request->attributes->get('node');
38+
3539
// Get the size query parameter.
3640
$size = (int) $request->query('size');
3741
if (empty($size)) {
3842
throw new BadRequestHttpException('A non-empty "size" query parameter must be provided.');
3943
}
4044

41-
/** @var \Pterodactyl\Models\Backup $backup */
42-
$backup = Backup::query()->where('uuid', $backup)->firstOrFail();
45+
/** @var \Pterodactyl\Models\Backup $model */
46+
$model = Backup::query()
47+
->where('uuid', $backup)
48+
->firstOrFail();
49+
50+
// Check that the backup is "owned" by the node making the request. This avoids other nodes
51+
// from messing with backups that they don't own.
52+
/** @var \Pterodactyl\Models\Server $server */
53+
$server = $model->server;
54+
if ($server->node_id !== $node->id) {
55+
throw new HttpForbiddenException('You do not have permission to access that backup.');
56+
}
4357

4458
// Prevent backups that have already been completed from trying to
4559
// be uploaded again.
46-
if (!is_null($backup->completed_at)) {
60+
if (!is_null($model->completed_at)) {
4761
throw new ConflictHttpException('This backup is already in a completed state.');
4862
}
4963

@@ -54,7 +68,7 @@ public function __invoke(Request $request, string $backup): JsonResponse
5468
}
5569

5670
// The path where backup will be uploaded to
57-
$path = sprintf('%s/%s.tar.gz', $backup->server->uuid, $backup->uuid);
71+
$path = sprintf('%s/%s.tar.gz', $model->server->uuid, $model->uuid);
5872

5973
// Get the S3 client
6074
$client = $adapter->getClient();
@@ -92,7 +106,7 @@ public function __invoke(Request $request, string $backup): JsonResponse
92106
}
93107

94108
// Set the upload_id on the backup in the database.
95-
$backup->update(['upload_id' => $params['UploadId']]);
109+
$model->update(['upload_id' => $params['UploadId']]);
96110

97111
return new JsonResponse([
98112
'parts' => $parts,

app/Http/Controllers/Api/Remote/Backups/BackupStatusController.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,22 @@ public function __construct(private BackupManager $backupManager)
3030
*/
3131
public function index(ReportBackupCompleteRequest $request, string $backup): JsonResponse
3232
{
33+
// Get the node associated with the request.
34+
/** @var \Pterodactyl\Models\Node $node */
35+
$node = $request->attributes->get('node');
36+
3337
/** @var \Pterodactyl\Models\Backup $model */
34-
$model = Backup::query()->where('uuid', $backup)->firstOrFail();
38+
$model = Backup::query()
39+
->where('uuid', $backup)
40+
->firstOrFail();
41+
42+
// Check that the backup is "owned" by the node making the request. This avoids other nodes
43+
// from messing with backups that they don't own.
44+
/** @var \Pterodactyl\Models\Server $server */
45+
$server = $model->server;
46+
if ($server->node_id !== $node->id) {
47+
throw new HttpForbiddenException('You do not have permission to access that backup.');
48+
}
3549

3650
if ($model->is_successful) {
3751
throw new BadRequestHttpException('Cannot update the status of a backup that is already marked as completed.');

app/Http/Requests/Admin/Egg/EggFormRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public function rules(): array
1111
$rules = [
1212
'name' => 'required|string|max:191',
1313
'description' => 'nullable|string',
14-
'docker_images' => 'required|string',
14+
'docker_images' => ['required', 'string', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/im'],
1515
'force_outgoing_ip' => 'sometimes|boolean',
1616
'file_denylist' => 'array',
1717
'startup' => 'required|string',

app/Http/Requests/Admin/Nest/StoreNestFormRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class StoreNestFormRequest extends AdminFormRequest
99
public function rules(): array
1010
{
1111
return [
12-
'name' => 'required|string|min:1|max:191',
12+
'name' => 'required|string|min:1|max:191|regex:/^[\w\- ]+$/',
1313
'description' => 'string|nullable',
1414
];
1515
}

app/Http/Requests/Api/Client/Servers/Settings/SetDockerImageRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public function rules(): array
2424
Assert::isInstanceOf($server, Server::class);
2525

2626
return [
27-
'docker_image' => ['required', 'string', Rule::in(array_values($server->egg->docker_images))],
27+
'docker_image' => ['required', 'string', 'max:191', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/', Rule::in(array_values($server->egg->docker_images))],
2828
];
2929
}
3030
}

0 commit comments

Comments
 (0)