Skip to content

← Public intelligence

Packagist package

thorsten/phpmyfaq

Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.

Open advisories

110 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.

  1. High, CVSS 8.5PackagistAmendedPublished

    phpMyFAQ has SQL Injection in StopWords::add() — Unescaped Stop Word Insertion

    CVE-2026-56738 · GHSA-rw77-vq4g-x3hp

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.5
    Fixed in
    4.1.6· Vendor fix available
    Issue
    The StopWords::add() method in phpMyFAQ builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path. An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database. --- Affected Code File: phpmyfaq/src/phpMyFAQ/StopWords.php Method: add() (approx. lines 60–75 in the audited revision) $word is taken directly from the administrative form input (the new stop word to add) and concatenated into the SQL string via sprintf("'%s'", ...) with no call to the…

    Recommended action: Upgrade to 4.1.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  2. High, CVSS 8.1PackagistAmendedPublished

    phpMyFAQ's two-factor authentication login bypasses the password factor

    CVE-2026-56737 · GHSA-8gpw-xvpf-hvx5

    Affected
    • Packagist thorsten/phpmyfaq >= 3.2.0, < 4.1.6
    Fixed in
    4.1.6· Vendor fix available
    Issue
    The public two-factor verification endpoint POST /check logs a user in based solely on a valid 6-digit TOTP token and a chosen user-id. It does not require — and is not bound to — a prior successful password authentication. For any account that has 2FA enabled, an unauthenticated attacker can authenticate without knowing the password, reducing the account to a single factor (a 6-digit code) that is itself brute-forceable because this endpoint has no lockout (see Finding #2). This is an authentication bypass of the primary credential for all 2FA-protected accounts, including administrators. Details src/phpMyFAQ/Controller/Frontend/AuthenticationController.php:255-283: twoFactorSuccess() performs a complete session login (src/phpMyFAQ/User/CurrentUser.php:239-247): There is no server-side state (such as a "password already verified for this user" flag) tying the /check step to the password step. Compare the admin flow, which does it correctly via a 2fapendinguserid session…

    Recommended action: Upgrade to 4.1.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  3. High, CVSS 8.2PackagistAmendedPublished

    phpMyFAQ has Stored XSS in Admin FAQ Editor via HTML Entity Bypass in Frontend FAQ Submission

    CVE-2026-56736 · GHSA-pgwp-vc7q-cvj3

    Affected
    • Packagist thorsten/phpmyfaq < 4.2.0-alpha
    Fixed in
    4.2.0-alpha· Vendor fix available
    Issue
    A stored cross-site scripting (XSS) vulnerability in phpMyFAQ allows any unauthenticated user (or low-privileged registered user) to inject arbitrary JavaScript that executes in an administrator's browser when they review or edit a user-submitted FAQ entry. This leads to admin account takeover via session theft. The vulnerability exists because htmlentitydecode() converts HTML entities into executable HTML after striptags() has already passed them through, and the admin template renders the content with Twig's |raw filter without any output sanitization. Details Vulnerable file: phpmyfaq/src/phpMyFAQ/Controller/Frontend/Api/FaqController.php (lines 109-115) Root cause: Filter::filterVar() with FILTERSANITIZESPECIALCHARS internally calls filterSanitizeString() which applies striptags() to remove HTML tags. However, striptags() only removes actual HTML tag syntax (e.g., <script) — it does NOT remove HTML entities (e.g., &lt;script&gt;). When enableWysiwygEditorFrontend is true,…

    Recommended action: Upgrade to 4.2.0-alpha (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  4. High, CVSS 8.8PackagistAmendedPublished

    phpMyFAQ privilege escalation: GroupController::updatePermissions lets a GROUP_EDIT admin grant rights they do not hold

    CVE-2026-57995 · GHSA-pg62-f8g4-4wqh

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.4
    Fixed in
    4.1.5· Vendor fix available
    Issue
    When phpMyFAQ hardened its admin permission-assignment endpoints against privilege escalation, it added a "a non-SuperAdmin may only assign rights they themselves hold" constraint to the user-rights endpoint (UserController::updateUserRights). The equivalent group-rights endpoint, GroupController::updatePermissions, did not receive that constraint. A delegated administrator holding only the GROUPEDIT permission can therefore grant any group an arbitrary set of rights — including rights the administrator does not possess — and, by being (or becoming) a member of that group, inherit those rights, escalating to higher privileges up to full administrative control. Impact phpMyFAQ supports delegated administration: the GROUPEDIT right can be granted to a non-SuperAdmin so they can manage groups. Such an administrator can escalate: 1. They call POST /admin/group/update/permissions with groupid set to a group they belong to (or can manage membership of) and grouprights[] containing…

    Recommended action: Upgrade to 4.1.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  5. Medium, CVSS 5.3PackagistAmendedPublished

    phpMyFAQ public FAQ APIs expose inactive FAQ content

    CVE-2026-57994 · GHSA-mf8r-wm2w-f8c5

    Affected
    • Packagist thorsten/phpmyfaq >= 4.1.0, <= 4.1.4
    Fixed in
    4.1.5· Vendor fix available
    Issue
    Affected Product phpMyFAQ Affected Versions - Confirmed affected: 4.1.4, API v3.1. - Confirmed affected: current main / 4.2-style source, API v4.0, for GET /api/v4.0/faqs/tags/{tagId} when api.onlyActiveFaqs=true. Patched Versions 4.1.5. Description The public FAQ API applies inconsistent active = 'yes' filtering across endpoints. A FAQ entry marked active = 'no' is hidden from GET /api/v3.1/faqs/{categoryId} in phpMyFAQ 4.1.4, but the same inactive FAQ can still be retrieved through public API routes: - GET /api/v3.1/faq/{categoryId}/{faqId} returns the inactive FAQ title and full answer. - GET /api/v3.1/faqs/tags/{tagId} returns the inactive FAQ title and answer preview. On the current 4.2-style branch, api.onlyActiveFaqs=true hides inactive FAQs from list and direct-by-id endpoints, but GET /api/v4.0/faqs/tags/{tagId} still returns inactive FAQ title and preview because it calls Faq::getFaqsByIds() without active/date filtering. Inactive FAQs are commonly used as drafts or…

    Recommended action: Upgrade to 4.1.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  6. Medium, CVSS 4.9PackagistAmendedPublished

    phpMyFAQ has Potential Authenticated Path Traversal in PDF Export

    CVE-2026-57961 · GHSA-88g4-74f3-63x9

    Affected
    • Packagist thorsten/phpmyfaq >= 4.0.0-alpha, <= 4.1.4
    Fixed in
    4.1.5· Vendor fix available
    Issue
    There is an authenticated path traversal condition in the PDF export functionality, specifically within the PDF image resolution logic. The issue may allow a privileged FAQ editor to cause the application to attempt reading files outside the intended content directory during PDF generation. --- Affected Component File: src/phpMyFAQ/Export/Pdf/Wrapper.php Function: concatenatePaths() --- Root Cause The path resolution logic relies on locating the substring "content" within a user-controlled path: If "content" is not present, strpos() returns false, which becomes 0 when cast to an integer. As a result, the entire attacker-controlled path is preserved. Example: The resulting path is later processed by: without canonicalization or a root-directory containment check. --- Observed Data Flow --- Potential Impact Based on code review, a user with FAQ editing privileges may be able to store HTML containing crafted image paths that are processed during PDF generation. Potential…

    Recommended action: Upgrade to 4.1.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  7. Medium, CVSS 5.4PackagistAmendedPublished

    phpMyFAQ: SQL LIKE Wildcard Injection in Chat User Search Allows Authenticated User Enumeration

    CVE-2026-47132 · GHSA-6pvm-2vjj-rx4w

    Affected
    • Packagist thorsten/phpmyfaq < 4.2.0-alpha
    Fixed in
    4.2.0-alpha· Vendor fix available
    Issue
    An authenticated SQL LIKE wildcard injection vulnerability in phpMyFAQ’s chat user search allows any logged-in user to bypass the intended display-name search filter and enumerate active users. The endpoint escapes SQL string syntax but does not escape % and , which remain active LIKE wildcards. Details The vulnerable endpoint is: Source: Sink: escape() prevents SQL string breakout, but it does not escape SQL LIKE metacharacters. Therefore, attacker-controlled % and are interpreted by the database as wildcards. The project already uses a safer pattern elsewhere with ESCAPE '|' and wildcard escaping, but this chat search path does not apply it. PoC: Tested against: phpMyFAQ 4.2.0-alpha commit c0b7158df4bfb11d57b1ef7d471760583c9c2fae Prerequisite: attacker has any valid authenticated user account. 1. Ensure there are multiple active users in the database, for example: 2. Send a normal query that should not match any user: Observed response: 3. Send a wildcard query:…

    Recommended action: Upgrade to 4.2.0-alpha (pre-release) or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:osv.dev (1)github.com (2)Source checked Evidence →
  8. High, CVSS 8.1PackagistPublished

    phpMyFAQ has an incomplete fix for GHSA-xvp4-phqj-cjr3 — editUser() and updateUserRights() lack authorization guards

    GHSA-985r-q3qp-299h

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.3
    Fixed in
    4.1.4· Vendor fix available
    Issue
    Advisory / Disclosure phpMyFAQ 4.1.3 — incomplete fix for the admin-API IDOR/privilege-escalation class Target: thorsten/phpMyFAQ (composer: thorsten/phpmyfaq, phpmyfaq/phpmyfaq) Affected: <= 4.1.3 (the 4.1.3 security fix is incomplete; siblings remain) Class: CWE-862 Missing Authorization / CWE-269 Improper Privilege Management / CWE-639 Authorization Bypass Through User-Controlled Key Methodology: M1 incomplete-fix audit (sibling-walk of the 4.1.3 fix for GHSA-xvp4-phqj-cjr3) Severity: High — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 8.8 (same class as the parent CVE) Summary phpMyFAQ 4.1.3 fixed GHSA-xvp4-phqj-cjr3 ("IDOR Account Takeover") by adding actor-authorization guards to UserController::overwritePassword(). The patch establishes a new invariant, stated in its own code comments: "Only SuperAdmins may change other users' [attributes]. Self-service is always allowed." and "a non-SuperAdmin must never be able to alter a SuperAdmin or protected account." That invariant is…

    Recommended action: Upgrade to 4.1.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  9. Medium, CVSS 6.5PackagistPublished

    phpMyFAQ: Missing userHasPermission() in 4 API write endpoints (CVE-2026-24421 Incomplete Fix)

    CVE-2026-49205 · GHSA-8c6h-7g6x-m5x4

    Affected
    • Packagist thorsten/phpmyfaq < 4.1.4
    Fixed in
    4.1.4· Vendor fix available
    Issue
    Missing Authorization in API CategoryController — CVE-2026-24421 fixed BackupController by adding userHasPermission(PermissionType::BACKUP). The same fix was NOT applied to 4 other write endpoints in the public API. All 4 only call hasValidToken() (shared API key) but never call userHasPermission(), allowing any API token holder to perform admin operations regardless of their user permissions. Summary CVE-2026-24421 fixed BackupController by adding: $this-userHasPermission(PermissionType::BACKUP); The same fix was NOT applied to 4 other write endpoints in the public API. All 4 only call $this-hasValidToken() — which checks a shared API key header, NOT the individual user's role permissions. Affected Endpoints 1. src/phpMyFAQ/Controller/Api/CategoryController.php → create() POST /api/v4.0/category Missing: userHasPermission(PermissionType::CATEGORYADD) Any API token holder can create categories regardless of user role. 2. src/phpMyFAQ/Controller/Api/FaqController.php → create() POST…

    Recommended action: Upgrade to 4.1.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  10. Low, CVSS 2.7PackagistPublished

    phpMyFAQ has Weak Cryptography - SHA1 for Password Hashing

    CVE-2026-48488 · GHSA-58fg-62fg-3fcj

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.3
    Fixed in
    4.1.4· Vendor fix available
    Issue
    Attachment passwords are hashed using SHA-1, a cryptographically broken algorithm. SHA-1 has been vulnerable to collision attacks since 2017 (SHAttered). Details Affected File : phpmyfaq/src/phpMyFAQ/Attachment/AbstractAttachment.php <img width="810" height="427" alt="image" src="https://github.com/user-attachments/assets/6499a008-3ece-4291-8296-f1d3303ba35c" / Impact - An attacker can generate SHA-1 collisions to bypass attachment protection - Risk of password cracking if database is compromised - Estimated cracking time: < 1 minute for standard attachment Solution Use bcrypt:

    Recommended action: Upgrade to 4.1.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  11. High, CVSS 8.2PackagistPublished

    phpMyFAQ: Missing Password Reset Token Allows Account Takeover via Username/Email Enumeration

    CVE-2026-35675 · GHSA-w9xh-5f39-vq89

    Affected
    • Packagist thorsten/phpmyfaq < 4.1.3
    Fixed in
    4.1.3· Vendor fix available
    Issue
    An authentication bypass vulnerability in phpMyFAQ allows any unauthenticated attacker to reset the password of any user account, including SuperAdmin accounts. By sending a PUT request with just a valid username and associated email address to /api/user/password/update, an attacker receives a new plaintext password via email without any token verification, rate limiting, or email confirmation. This enables complete account takeover of any user, including full administrative access. Details File: phpmyfaq/src/phpMyFAQ/Controller/Frontend/Api/UnauthorizedUserController.php Lines: 56-130 The updatePassword() method at line 56 accepts PUT requests to /user/password/update with only username and email in the JSON body: #[Route(path: 'user/password/update', name: 'api.private.user.password', methods: ['PUT'])] Root Causes: 1. No time-limited cryptographic token required for password reset 2. No rate limiting on the endpoint (allows unlimited username/email enumeration) 3. No…

    Recommended action: Upgrade to 4.1.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  12. High, CVSS 8.7PackagistPublished

    phpMyFAQ: Default Empty API Token Authentication Bypass

    CVE-2026-35672 · GHSA-gp95-j463-vv28

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.2
    Fixed in
    4.1.3· Vendor fix available
    Issue
    A default empty API client token allows any unauthenticated user to create and modify FAQ entries, categories, and questions via the REST API. The vulnerability exists in all versions since API v4.0 was introduced because the installation process seeds api.apiClientToken with an empty string, and the hasValidToken() comparison logic cannot distinguish between "no token configured" and "attacker sent a matching empty token header." Details The root cause is in two files: 1. Installation default (src/phpMyFAQ/Setup/Installation/DefaultDataSeeder.php, line 277-278): 2. Authentication check (src/phpMyFAQ/Controller/AbstractController.php, line 198-204): The method uses strict inequality (!==). When api.apiClientToken is '' (default) and the attacker sends x-pmf-token: (empty header value), the comparison becomes '' !== '' which evaluates to false — no exception is thrown, and authentication is completely bypassed. The OpenAPI annotations confirm the developer intended these…

    Recommended action: Upgrade to 4.1.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  13. High, CVSS 8.8PackagistPublished

    phpMyFAQ: IDOR Account Takeover

    CVE-2026-35671 · GHSA-xvp4-phqj-cjr3

    Affected
    • Packagist thorsten/phpmyfaq < 4.1.3
    Fixed in
    4.1.3· Vendor fix available
    Issue
    An Insecure Direct Object Reference (IDOR) vulnerability in phpMyFAQ's Admin API allows any authenticated administrator to change the password of any user account, including SuperAdmin accounts (userId=1), without authorization verification. An attacker with a low-privilege admin account can escalate privileges to full SuperAdmin control by simply changing the target user's ID in the API request body. Details File: phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/UserController.php Lines: 232-271 The overwritePassword() method at line 232 accepts PUT requests to /admin/api/user/overwrite-password: #[Route(path: 'user/overwrite-password', name: 'admin.api.user.overwrite-password', methods: ['PUT'])] Root Causes: 1. No verification that the requesting admin has permission to modify the target user's password 2. No check that the target user has equal or lower privilege level 3. The userId is taken directly from the request body without authorization context 4. No…

    Recommended action: Upgrade to 4.1.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  14. High, CVSS 8.2PackagistPublished

    phpMyFAQ: Unauthenticated Password Reset Endpoint Allows User Enumeration and Forced Password Change Without Token Validation

    CVE-2026-35676 · GHSA-9qv9-8xv6-5p35

    Affected
    • Packagist thorsten/phpmyfaq < 4.1.3
    Fixed in
    4.1.3· Vendor fix available
    Issue
    The password reset API can be triggered without authentication and without any out-of-band confirmation step. If an attacker knows a valid username + email pair, they can call the reset endpoint directly. The application immediately generates a new password, writes it to the account, and only then sends the new password by email. This creates two issues at the same time: - account enumeration through the response difference between valid and invalid pairs - forced password reset of another user's account, which invalidates the old password immediately In my local reproduction, I confirmed both the response difference and the password change itself. Details The relevant code is in phpmyfaq/src/phpMyFAQ/Controller/Frontend/Api/UnauthorizedUserController.php. The route is exposed without authentication: The flow is straightforward: The core issue is that the password is changed immediately after a simple username and email match. There is no reset token, no confirmation link, no…

    Recommended action: Upgrade to 4.1.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  15. Critical, CVSS 9.8PackagistPublished

    phpMyFAQ has unauthenticated SQL injection via User-Agent header in BuiltinCaptcha

    CVE-2026-46364 · GHSA-289f-fq7w-6q2w

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    BuiltinCaptcha::garbageCollector() and BuiltinCaptcha::saveCaptcha() at phpmyfaq/src/phpMyFAQ/Captcha/BuiltinCaptcha.php:298 and :330 interpolate the User-Agent header and client IP address into DELETE and INSERT queries with sprintf and no escaping. Both methods run on every hit to the public GET /api/captcha endpoint, which requires no authentication. An unauthenticated attacker sets the User-Agent header to a crafted SQL payload and runs SLEEP(), BENCHMARK(), or time-based blind extraction against the database that backs phpMyFAQ. Verified live against 4.2.0-alpha (master at b9f25109): baseline request 147 ms, request with User-Agent: x' OR SLEEP(2) OR 'x 4.09 s (two SLEEP(2) calls, one per vulnerable sink). Details phpmyfaq/src/phpMyFAQ/Captcha/BuiltinCaptcha.php:112 populates two private fields from untrusted HTTP input at construction time: Both fields are then dropped into sprintf() SQL templates without ever touching Database::escape() or a prepared statement.…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  16. Medium, CVSS 6.5PackagistPublished

    phpMyFAQ: Path Traversal in Client::deleteClientFolder enables arbitrary directory deletion by non-super-admin admins

    CVE-2026-45008 · GHSA-gh9p-q46p-57g2

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    Client::deleteClientFolder() in phpmyfaq/src/phpMyFAQ/Instance/Client.php:583 takes a URL from the caller, strips the https:// prefix, and passes the remainder to Filesystem::deleteDirectory() relative to the multisite clientFolder. No path-traversal validation runs. An admin with the INSTANCEDELETE permission (a role short of SUPERADMIN) submits https://../../../<path as the client URL and the server recursively deletes arbitrary directories under the web user's rights. Same pattern and reachability as GHSA-38m8-xrfj-v38x, which the project accepted at High severity three weeks earlier. Details phpmyfaq/src/phpMyFAQ/Instance/Client.php:583-591: strreplace strips the scheme but does nothing about ../ segments. The concatenation $this-clientFolder . $sourcePath directly feeds the filesystem call, which traverses above clientFolder without complaint. Callers feed the URL from the HTTP request body: phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/InstanceController.php:184:…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  17. High, CVSS 7.5PackagistPublished

    phpMyFAQ has unauthenticated FAQ permission bypass via getFaqBySolutionId fallback query

    CVE-2026-46366 · GHSA-99qv-g4x9-mgc3

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    The public /solutionid{id}.html route calls Faq::getIdFromSolutionId() in phpmyfaq/src/phpMyFAQ/Faq.php:1312. That query joins faqdata with faqcategoryrelations solely by solutionid and returns the matching FAQ's id, lang, thema (title), and categoryid with no permission filter. An unauthenticated visitor hits the route with a sequential integer and the server 301-redirects to /content/<category/<id/<lang/<title-slug.html, leaking the FAQ's existence, internal id, language, category binding, and title via the redirect's Location header and the redirected page's canonical link, share-to-social URLs, and hidden form fields. The related getFaqBySolutionId() at line 1221 contains an explicit fallback query (added "for tests") that also bypasses the permission filter, widening the blast radius to any callsite that trusts its result. Details The sink: getIdFromSolutionId() has no permission filter phpmyfaq/src/phpMyFAQ/Faq.php:1312: No WHERE-clause permission filter, no group/user…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  18. High, CVSS 7.5PackagistPublished

    phpMyFAQ has SQL Injection in CurrentUser::setTokenData through unescaped OAuth token fields

    CVE-2026-46359 · GHSA-pm8c-3qq3-72w7

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    CurrentUser::setTokenData() in phpmyfaq/src/phpMyFAQ/User/CurrentUser.php at lines 515-534 builds a SQL UPDATE statement with sprintf and interpolates OAuth token fields (refreshtoken, accesstoken, codeverifier, and jsonencode($token['jwt'])) without calling $db-escape(). Sibling methods setAuthSource() and setRememberMe() in the same file do call $db-escape() on user-controlled values, so the omission is local to this method. An attacker (Bob) whose Azure AD display name contains a single quote (for example O'Brien, or a deliberate SQL payload) breaks out of the string literal and injects arbitrary SQL against the phpMyFAQ database. Details Vulnerable code (phpmyfaq/src/phpMyFAQ/User/CurrentUser.php, lines 513-534): jsonencode() does NOT escape single quotes. A JWT claim such as {"preferredusername": "O'Malley"} produces {"preferredusername":"O'Malley"} after jsonencode, which terminates the SQL string literal at the apostrophe. Correct pattern in the same file…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  19. Critical, CVSS 9.1PackagistPublished

    phpMyFAQ enables unauthenticated 2FA brute-force attack via /admin/check acceptance of arbitrary user-id

    CVE-2026-45010 · GHSA-9pq7-mfwh-xx2j

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    The /admin/check endpoint in AuthenticationController implements SkipsAuthenticationCheck, making it reachable without any prior authentication. An anonymous attacker (Bob) can POST arbitrary user-id and token values to brute-force any user's 6-digit TOTP code. No rate limiting exists. The 10^6 keyspace is exhaustible in minutes. Reachability confirmed against a default install: unauthenticated POST /admin/check with a user-id body field returns HTTP 302 to /admin/token?user-id=<value, echoing the attacker-supplied user id without any binding to a prior password-phase authentication. Details File: phpmyfaq/src/phpMyFAQ/Controller/Administration/AuthenticationController.php, lines 35-36 and 201-228. The controller class declaration: The SkipsAuthenticationCheck interface (phpmyfaq/src/phpMyFAQ/Controller/Administration/SkipsAuthenticationCheck.php) is a marker interface that tells the ControllerContainerListener to skip authentication enforcement. Every route in this…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  20. Medium, CVSS 4.3PackagistPublished

    phpMyFAQ: Ordinary Authenticated User Can Access Admin-Only API Endpoints Due to Insufficient Authorization Check in phpMyFAQ

    CVE-2026-45009 · GHSA-jrc5-w569-h7h5

    Affected
    • Packagist thorsten/phpmyfaq >= 4.1.1, <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    A review of phpMyFAQ-main uncovered an authorization issue in the admin-api routes. Several backend endpoints only check whether the caller is logged in. They do not verify that the caller actually has backend or administrative privileges. As a result, a normal frontend user can access API endpoints that are clearly intended for administrative use. During local reproduction, a regular user account was able to request /admin/api/index.php/dashboard/versions and receive a successful response from the backend management API. This issue does not appear to give direct write access in the affected paths that were confirmed, so it should be treated as a backend information disclosure and privilege boundary failure rather than full admin compromise. Details The access control split is visible in the controller base class: The problem is that several Administration\Api controllers use the weaker check even though the routes sit under the backend API namespace. For example,…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  21. Medium, CVSS 6.9PackagistPublished

    phpMyFAQ has stored XSS via | raw Filter in search.twig — html_entity_decode(strip_tags()) Bypass in Search Result Rendering

    CVE-2026-46361 · GHSA-pqh6-8fxf-jx22

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    The search result rendering template (search.twig) outputs FAQ content fields result.question and result.answerPreview using Twig's | raw filter, which completely disables the template engine's built-in auto-escaping. A user with FAQ editor/contributor privileges can store a payload encoded as HTML entities. During search result construction, htmlentitydecode(striptags(...)) restores the raw HTML tags — bypassing striptags() — and the restored payload is injected into every visitor's browser via the | raw output. This vulnerability is distinct from GHSA-cv2g-8cj8-vgc7 (affects faq.twig, bypass via regex mismatch in Filter::removeAttributes()) and is not addressed by the 4.1.1 patch. --- Affected Files | File | Location | Issue | |---|---|---| | phpmyfaq/assets/templates/default/search.twig | lines rendering result.question, result.answerPreview | (Vertical Bar) raw disables autoescape | | phpmyfaq/src/phpMyFAQ/Controller/Api/SearchController.php | search result processing…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  22. Medium, CVSS 4.3PackagistPublished

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

    CVE-2026-45007 · GHSA-rm98-82fr-mcfx

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    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: The remaining 12 only check that the user is logged in: The difference between these two methods is significant: 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 |…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  23. Medium, CVSS 5.4PackagistPublished

    phpMyFAQ has a SVG Sanitizer Entity Decoding Depth Limit Bypass Leading to Stored XSS

    CVE-2026-46360 · GHSA-whqh-9pq5-c7r3

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    The SvgSanitizer::decodeAllEntities() method limits recursive entity decoding to 5 iterations. By wrapping each character of javascript in an href attribute value with 5 levels of &amp; encoding around numeric HTML entities (e.g., &amp;amp;amp;amp;amp;#106; for j), an attacker can bypass both isSafe() detection and sanitize() removal. The uploaded SVG is served from the application origin with image/svg+xml content type, and the browser's XML parser fully decodes the remaining &#NNN; entities, resulting in a clickable javascript: link that executes arbitrary JavaScript. Details Root cause: decodeAllEntities() at phpmyfaq/src/phpMyFAQ/Helper/SvgSanitizer.php:223-249 limits entity decoding to maxIterations=5. Each iteration: (1) decodes &#NNN; numeric entities, (2) decodes &#xHH; hex entities, (3) calls htmlentitydecode() which resolves one level of &amp; → &. With 5 levels of &amp; wrapping, all 5 iterations are consumed unwinding the &amp; nesting, leaving the final &#NNN;…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  24. Medium, CVSS 5.4PackagistPublished

    phpMyFAQ has Stored XSS in FAQ Question/Answer via Encode-Decode Bypass of removeAttributes() Sanitization

    CVE-2026-46363 · GHSA-f5p7-2c9q-8896

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    The FAQ creation and update endpoints in phpMyFAQ apply FILTERSANITIZESPECIALCHARS (which HTML-encodes input), then immediately call htmlentitydecode() which reverses the encoding, followed by Filter::removeAttributes() which only strips HTML attributes — not tags. This allows <script, <iframe, <object, and <embed tags to be stored in the database and rendered unescaped via {{ answer|raw }} and {{ question|raw }} in the Twig template, causing JavaScript execution in every visitor's browser. Details Vulnerable code path (FAQ create — FaqController.php): At line 120, the answer content is filtered: Filter::filterVar() calls filterSanitizeString() (Filter.php:135-144) which applies htmlspecialchars(), converting <script to &lt;script&gt;. The regex /\x00|<[^]?/ then finds no literal angle brackets to strip. At lines 150-154, the encoded content is decoded and passed to attribute-only sanitization: htmlentitydecode() converts &lt;script&gt; back to <script, fully reversing the…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  25. Medium, CVSS 5.4PackagistPublished

    phpMyFAQ's Missing Authorization on Tag Deletion Allows Any Authenticated User to Delete Tags

    GHSA-7cx3-2qx2-3g6w

    Affected
    • Packagist thorsten/phpmyfaq <= 4.1.1
    Fixed in
    4.1.2· Vendor fix available
    Issue
    The TagController::delete() endpoint at DELETE /admin/api/content/tags/{tagId} only verifies that the user is logged in (userIsAuthenticated()), but does not check any permission. Any authenticated user — including regular non-admin frontend users — can delete any tag by ID. This contrasts with TagController::update() and TagController::search(), which both enforce the FAQEDIT permission. Details In phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/TagController.php, the delete() method (line 121-133) uses only $this-userIsAuthenticated(): Compare with update() (line 48-71) which properly enforces authorization: The userIsAuthenticated() method in AbstractController (line 258-263) only checks $this-currentUser-isLoggedIn(): There is no admin-level middleware in the Kernel — it registers only RouterListener, LanguageListener, ControllerContainerListener, and exception listeners. The admin API entry point (admin/api/index.php) shares the same bootstrap and session as the…

    Recommended action: Upgrade to 4.1.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →