GHSA-mf8r-wm2w-f8c5: phpMyFAQ public FAQ APIs expose inactive FAQ content
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 review-only content, so these unauthenticated public API paths may disclose non-public content.
Root Cause
FaqController::getByCategoryId() calls Faq::getAllAvailableFaqsByCategoryId(), which filters:
fd.date_start <= now
AND fd.date_end >= now
AND fd.active = 'yes'
FaqController::getByTagId() instead resolves record IDs through Tags::getFaqsByTagId() and then calls Faq::getFaqsByIds($recordIds).
Faq::getFaqsByIds() filters by record ID, language, and permission, but does not filter fd.active = 'yes' or publication date windows before returning record_title and record_preview.
In phpMyFAQ 4.1.4, FaqController::getById() calls Faq::getFaqByIdAndCategoryId(), which also lacks an inactive/publication-window filter and returns the full answer.
Proof of Concept
The attached PoC uses phpMyFAQ's real Composer autoloader, real public FaqController, and a temporary copy of tests/test.db.
Run from a local phpMyFAQ 4.1.4 source checkout after dependencies are installed and tests/test.db
Details
Original advisory: https://github.com/advisories/GHSA-mf8r-wm2w-f8c5
More from GitHub Security Advisories
- mediumGHSA-p43p-whwx-q52h: JupyterHub has Unauthenticated Denial of Service via Unbounded Username Logging on Failed…2026-08-25
- highGHSA-cv84-9p8j-fj68: icalendar has Algorithmic Complexity in Equality2026-08-25
- highGHSA-hvfh-5mj3-5f3j: Chainlist has SSRF via MCP SSE and streamable-http transports that allows unauthenticated…2026-08-25
- criticalGHSA-w3fx-mc44-mf6j: Chainlit has command injection via MCP stdio transport that allows unauthenticated remote…2026-08-25
- mediumGHSA-72f3-6w86-7rv3: @arikusi/deepseek-mcp-server: Missing Authentication on Self-Hosted HTTP MCP Endpoint2026-08-25