CVE-2026-45007: phpMyFAQ's Missing CONFIGURATION_EDIT Permission Check on 12 Admin API Configuration Tab Endpoints Allows Information Disclosure by Any Authenticated User

Published May 6, 2026
·
Updated

Summary

12 endpoints in ConfigurationTabController.php use userIsAuthenticated() (login-only check) instead of userHasPermission(PermissionType::CONFIGURATIONEDIT). This allows any authenticated user — including ones with zero admin permissions — to enumerate system configuration metadata including the permission model, active template, cache backend, mail provider, and translation provider.

Details

The ConfigurationTabController contains 15 public endpoints. Three of them (list, save, uploadTheme) correctly enforce CONFIGURATIONEDIT permission:

php // phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/ConfigurationTabController.php:63 public function list(Request $request): Response { $this->userHasPermission(PermissionType::CONFIGURATIONEDIT); // ✅ Correct // ... }

The remaining 12 only check that the user is logged in:

php // phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/ConfigurationTabController.php:353 public function translations(): Response { $this->userIsAuthenticated(); // ❌ Missing permission check // ... }

The difference between these two methods is significant:

php // AbstractController.php:258 — login-only protected function userIsAuthenticated(): void { if (!$this->currentUser->isLoggedIn()) { throw new UnauthorizedHttpException(challenge: 'User is not authenticated.'); } }

// AbstractController.php:317 — login + permission check protected function userHasPermission(PermissionType $permissionType): void { if (!$this->currentUser->isLoggedIn()) { throw new UnauthorizedHttpException(challenge: 'User is not authenticated.'); } $currentUser = $this->currentUser; if (!$currentUser?->perm->hasPermission($currentUser->getUserId(), $permissionType->value)) { throw new ForbiddenException(/ ... /); } }

There is no middleware or router-level authorization — the Kernel (Kernel.php) dispatches directly to controllers with only Language, Router, and Exception listeners. All authorization is at the controller method level.

The 12 affected endpoints (all GET, all under /admin/api/):

| # | Method | Route | Info Exposed | |---|--------|-------|-------------| | 1 | translations() | /configuration/translations | Available languages + current language | | 2 | templates() | /configuration/templates | Available themes + active theme | | 3 | faqsSortingKey() | /configuration/faqs-sorting-key/{current} | FAQ sorting key options | | 4 | faqsSortingOrder() | /configuration/faqs-sorting-order/{current} | FAQ sorting order | | 5 | faqsSortingPopular() | /configuration/faqs-sorting-popular/{current} | Popular FAQ sorting | | 6 | permLevel() | /configuration/perm-level/{current} | Permission model (basic/medium) | | 7 | releaseEnvironment() | /configuration/release-environment/{current} | Dev/production environment | | 8 | searchRelevance() | /configuration/search-relevance/{current} | Search relevance config | | 9 | seoMetaTags() | /configuration/seo-metatags/{current} | SEO meta tag config | | 10 | translationProvider() | /configuration/translation-provider/{current} | Translation service (DeepL, etc.) | | 11 | mailProvider() | /configuration/mail-provider/{current} | Mail provider (SMTP, etc.) | | 12 | cacheAdapter() | /configuration/cache-adapter/{current} | Cache backend (filesystem/redis/memcached) |

The translations() and templates() endpoints directly read from config/filesystem and expose current settings. The {current} endpoints render HTML <option> dropdowns where the caller-supplied value gets the selected attribute — an attacker can enumerate possible values to discover the current configuration.

PoC

bash Step 1: Authenticate as any user (even one with no admin permissions) and obtain the session cookie (pmfauthXXXX)

Step 2: Query configuration endpoints that should require CONFIGURATIONEDIT permission

Enumerate available languages and current language setting curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/translations

Enumerate available templates and which is active curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/templates

Discover permission model by trying known values curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/perm-level/basic

Discover release environment curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/release-environment/development

Discover cache backend curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/cache-adapter/filesystem

Discover mail provider curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/mail-provider/smtp

Discover translation provider curl -s -b 'pmfauthXXXX=<session>' \ https://target.example/admin/api/configuration/translation-provider/deepl

Expected: HTTP 403 Forbidden for a user without configurationedit permission. Actual: HTTP 200 with configuration data in HTML option format.

Impact

Any authenticated user (e.g., a regular FAQ contributor or a user with minimal permissions) can enumerate:

- The instance's permission model (basic vs. medium) — reveals access control architecture - Whether the instance runs in development or production mode — development mode may expose debug info - The cache backend (filesystem/redis/memcached) — useful for targeting cache-specific attacks - The mail provider configuration — reveals infrastructure details - Available and active templates/themes — aids in targeting template-specific vulnerabilities - Translation provider (e.g., DeepL) — reveals third-party service integrations

While no credentials or secrets are directly exposed, this configuration metadata aids targeted follow-up attacks and violates the principle of least privilege — these endpoints exist to serve the admin configuration UI and should require the same CONFIGURATIONEDIT permission as the list and save endpoints.

Recommended Fix

Replace $this->userIsAuthenticated() with $this->userHasPermission(PermissionType::CONFIGURATIONEDIT) in all 12 affected methods:

php // In ConfigurationTabController.php — apply to all 12 methods // Before (line 355, and equivalent in all others): $this->userIsAuthenticated();

// After: $this->userHasPermission(PermissionType::CONFIGURATIONEDIT);

Affected methods: translations(), templates(), faqsSortingKey(), faqsSortingOrder(), faqsSortingPopular(), permLevel(), releaseEnvironment(), searchRelevance(), seoMetaTags(), translationProvider(), mailProvider(), cacheAdapter().

Other sources

phpMyFAQ before 4.1.2 contains missing permission checks in ConfigurationTabController.php where 12 endpoints use userIsAuthenticated() instead of userHasPermission(CONFIGURATIONEDIT). Any authenticated user can enumerate system configuration metadata including permission model, cache backend, mail provider, and translation provider by querying /admin/api/configuration endpoints, violating least privilege access control.

— MITRE

phpMyFAQ's Missing CONFIGURATIONEDIT Permission Check on 12 Admin API Configuration Tab Endpoints Allows Information Disclosure by Any Authenticated User

— Packagist

Affected Software

5 affected componentsFixes available
PhpMyFaq phpmyfaq<4.1.2
composer/phpmyfaq/phpmyfaq<=4.1.1
composer/thorsten/phpmyfaq<=4.1.1
composer/phpmyfaq/phpmyfaq<=4.1.1
4.1.2
composer/thorsten/phpmyfaq<=4.1.1
4.1.2

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade composer/phpmyfaq/phpmyfaq to a version that resolves this vulnerability.

    Fixed in 4.1.2
  2. Upgrade

    Upgrade composer/thorsten/phpmyfaq to a version that resolves this vulnerability.

    Fixed in 4.1.2
  3. Upgrade

    Upgrade phpMyFAQ to a version that resolves this vulnerability.

    Fixed in 4.1.2

Event History

May 6, 2026
Advisory Published
via GitHub·08:24 PM
Data Sourced
via GitHub·08:24 PM
DescriptionSeverityWeaknessAffected Software
Data Sourced
via Packagist·08:24 PM
DescriptionSeverityAffected Software
May 15, 2026
CVE Published
via MITRE·06:36 PM
Data Sourced
via MITRE·06:36 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·07:17 PM
DescriptionSeverityWeakness

Frequently Asked Questions

1

What is the severity of CVE-2026-45007?

CVE-2026-45007 is classified as a medium severity vulnerability due to the potential for unauthorized information disclosure.

2

How do I fix CVE-2026-45007?

To fix CVE-2026-45007, upgrade phpMyFAQ to version 4.1.2 or higher where the missing permission checks have been addressed.

3

What kind of information is at risk due to CVE-2026-45007?

CVE-2026-45007 can lead to the disclosure of sensitive configuration information accessible to unauthenticated users.

4

Which software versions are affected by CVE-2026-45007?

CVE-2026-45007 affects phpMyFAQ versions prior to 4.1.2.

5

Is CVE-2026-45007 a coding error?

Yes, CVE-2026-45007 is due to a coding error where the application checks for user authentication instead of the necessary permissions.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203