Skip to content

Merge development hardening and upstream security fixes#1318

Draft
zombiesis wants to merge 6 commits intoCtrlpanel-gg:developmentfrom
zombiesis:development
Draft

Merge development hardening and upstream security fixes#1318
zombiesis wants to merge 6 commits intoCtrlpanel-gg:developmentfrom
zombiesis:development

Conversation

@zombiesis
Copy link
Copy Markdown

Summary

This PR brings the fork's development branch up to date with Ctrlpanel-gg/panel:development and preserves the local hardening work on top.

It includes:

  • the local auth, billing, server lifecycle, API, and admin security fixes
  • the newer upstream RBAC, escaping, XSS, and installer security fixes already on Ctrlpanel-gg/panel:development
  • a conflict-resolved merge that keeps both sets of changes instead of dropping one side

Main changes

  • Hardened admin access, application API token handling, scoped API authorization, and admin write permissions.
  • Tightened RBAC checks across admin controllers and datatable endpoints.
  • Reworked payment flows for PayPal, Stripe, Mollie, and Mercado Pago to validate callbacks more safely and handle failures idempotently.
  • Replaced abandoned/deprecated integration paths for reCAPTCHA and the older PayPal SDK.
  • Hardened server creation, upgrade, rollback, and Pterodactyl synchronization behavior.
  • Fixed legacy bugs across referrals, coupons, invoices, registration, notifications, dashboard/admin flows, and Blade/UI rendering.
  • Kept upstream fixes for stored XSS, output escaping, installer lock enforcement, and safer shell execution.

Merge notes

The main overlap was in:

  • admin controllers
  • settings update handling
  • installer bootstrap and shell execution

Conflict resolution kept the local validation and service-layer hardening while also keeping the latest upstream RBAC/XSS/security protections.

Verification

  • php artisan test -> 92 passed
  • PHP lint passed on all conflict-resolved files
  • Upstream development was merged locally before publishing this branch

- secure payment gateway callbacks, checkout paths, and webhook fulfillment
- close admin authorization gaps across settings, vouchers, coupons, partners, store, and user flows
- harden API token scope handling, sensitive-field exposure, notification ownership, and audit logging
- sanitize terms and invoice rich text, tighten activity logging, and add security headers
- fix race conditions around vouchers and billing, add unique voucher pivot migration, and improve test coverage
- refresh built frontend assets and include the security audit notes
- stop re-selecting the latest notification after inserting the fixture
- keep the generated notification UUID and assert against the exact record
- preserve the green full-suite result under combined test execution
- replace the abandoned reCAPTCHA and PayPal integrations with maintained internal/runtime implementations and updated payment gateway settings

- harden Discord OAuth, payment callbacks, referral handling, registration, API user/server sync, and Pterodactyl client parsing/ownership flows

- fix server creation and upgrade consistency, overview/dashboard aggregation, invoice numbering, notification batching, validation gaps, and active-client role handling

- update tests, frontend build artifacts, and archive both review reports with the second-pass fixes applied
Copilot AI review requested due to automatic review settings March 27, 2026 13:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges upstream development into the fork while preserving/expanding local hardening, focusing heavily on RBAC, API token scoping, XSS mitigation, safer installer behavior, and more defensive payment/server lifecycle logic.

Changes:

  • Added scoped, revocable application API tokens (abilities, expiry) + API audit trail + per-endpoint scope middleware.
  • Reduced XSS risk by sanitizing rich-text settings/content and tightening escaping across Blade views and datatables.
  • Hardened operational flows: installer lock behavior, payment callbacks, server billing/suspension, and concurrency-sensitive updates.

Reviewed changes

Copilot reviewed 180 out of 188 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
themes/default/vite.config.js Ensures Vite build manifest generation aligns with runtime asset loading.
themes/default/views/.blade.php + themes/BlueInfinity/ Escaping/sanitization improvements, safer POST actions (CSRF), and rel=noopener additions.
app/Support/HtmlSanitizer.php Introduces centralized rich-text sanitization used by settings and templates.
routes/api.php + app/Http/Middleware/* Adds API throttling, audit logging, and fine-grained scope enforcement.
database/migrations/* Adds API token table, encrypts existing secret settings, and adds uniqueness constraints for voucher redemption.
public/installer/** Tightens installer enablement rules and improves shell execution / SQL safety.
tests/** + phpunit.xml Updates tests for new auth/RBAC model and adds callback/authorization coverage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +55 to 64
'mail_encryption' => $_POST['encryption'] === 'null' ? null : $_POST['encryption'],
'mail_from_address' => $_POST['user'],
'mail_from_name' => $_POST['user'],
];

foreach ($values as $key => $value) {
wh_log("[MailSettings] Setting" . $key , 'debug');
$safeValue = escapeshellarg($value);

wh_log("[MailSettings] Setting " . $key , 'debug');
try {
run_console("php artisan settings:set 'MailSettings' '$key' $safeValue", null, null, null, false);
run_console("php artisan settings:set 'MailSettings' " . escapeshellarg($key) . ' ' . escapeshellarg((string) $value), null, null, null, false);
} catch (\Exception $e) {
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mail_encryption is normalized to null in $values, but the command building casts (string) $value before escapeshellarg(). When $value is null this becomes an empty string, so the installer will persist "" instead of null, changing semantics for nullable settings.

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +21
$envPath = __DIR__ . '/../.env';

if (! file_exists($envPath)) {
file_put_contents($envPath, '');
}

Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test bootstrap writes an empty .env file into the repository root when none exists. That introduces side effects (dirty working tree, potential permission issues in CI, and surprising local behavior) that tests should avoid. Prefer configuring env via phpunit.xml / $_ENV only, or use .env.testing rather than creating .env at runtime.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +29
$deduplicatedRows = DB::table('user_voucher')
->select(
'user_id',
'voucher_id',
DB::raw('MIN(created_at) as created_at'),
DB::raw('MIN(updated_at) as updated_at')
)
->groupBy('user_id', 'voucher_id')
->get();

DB::table('user_voucher')->delete();
foreach ($deduplicatedRows as $row) {
DB::table('user_voucher')->insert((array) $row);
}

Schema::table('user_voucher', function (Blueprint $table) {
$table->unique(['user_id', 'voucher_id']);
});
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This migration deletes all rows from user_voucher and reinserts the deduplicated set without wrapping the operation in a transaction. If the process is interrupted (or an insert fails) the table can be left partially empty/corrupted before the unique index is added. Consider wrapping the dedupe+delete+insert+index creation in a DB transaction (or using a safer in-place dedupe strategy) to make the migration atomic.

Copilot uses AI. Check for mistakes.
Comment on lines +70 to 73
@foreach (($useful_links ?? collect()) as $link)
<li class="nav-item d-none d-sm-inline-block">
<a href="{{ $link->link }}" class="nav-link" target="__blank"><i
class="{{ $link->icon }}"></i> {{ $link->title }}</a>
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useful links open in a new tab using target="__blank", which is not a valid target value (should be _blank). Also, links that open a new tab should include rel="noopener noreferrer" to prevent tabnabbing.

Copilot uses AI. Check for mistakes.
@MrWeez MrWeez marked this pull request as draft March 27, 2026 22:34
@MrWeez MrWeez added the Invalid This doesn't seem right label Mar 27, 2026
@simbabimba-dev simbabimba-dev modified the milestone: V1.2 Mar 30, 2026
@simbabimba-dev simbabimba-dev force-pushed the development branch 2 times, most recently from 8650200 to 32334b0 Compare April 13, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Invalid This doesn't seem right

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants