{"schema":"threatline.record/2","record":{"id":"GHSA-6x9g-rfx8-g42q","aliases":["GHSA-6x9g-rfx8-g42q"],"summary":"CSRF Allows Unauthorized Database Migrations via /admin/api/update-database","details":"## Summary\r\n\r\nThe `POST /admin/api/update-database` endpoint performs database migrations without requiring a CSRF token.\r\n\r\nThe endpoint only checks the global `CONFIGURATION_EDIT` permission and does not invoke the CSRF token validation mechanism used by other update-related endpoints.\r\n\r\n## Reproduction\r\n\r\nTested on phpMyFAQ `4.1.8`.\r\n\r\nA user with only the `editconfig` / `CONFIGURATION_EDIT` permission was logged in. The following request was sent without any CSRF token:\r\n\r\n```http\r\nPOST /admin/api/update-database HTTP/1.1\r\nHost: localhost:8080\r\nCookie: PHPSESSID=<u_conf-session>\r\nContent-Type: application/json\r\n\r\n{}\r\n```\r\n\r\nThe server returned:\r\n\r\n```json\r\n{\"success\":\"Database successfully updated.\"}\r\n```\r\n\r\nThe database migration was executed successfully despite the absence of a CSRF token.\r\n\r\n## Root Cause\r\n\r\n`updateDatabase()` does not call `Token::verifyToken()`.\r\n\r\nOther update-related endpoints use `isValidUpdatePackageToken()`, but the same protection is not applied to `update-database`.\r\n\r\n## Impact\r\n\r\nAn attacker can potentially trigger database migrations in a victim's authenticated browser through a cross-site request.\r\n\r\nDepending on the database state and migration being executed, this can cause database integrity or availability issues.\r\n\r\nThe endpoint is also accessible to users with the delegated `CONFIGURATION_EDIT` permission rather than being restricted to superadmins.\r\n\r\n## Remediation\r\n\r\nRequire a page-scoped CSRF token before executing database migrations:\r\n\r\n```php\r\nif (!Token::getInstance($this->container->get('session'))\r\n    ->verifyToken('update-database', $data->csrf)) {\r\n    return $this->json(\r\n        ['error' => Translation::get('msgNoPermission')],\r\n        Response::HTTP_UNAUTHORIZED\r\n    );\r\n}\r\n```\r\n\r\nThe authorization requirements for sensitive update operations should also be reviewed separately.\r\n","categories":["Unclassified"],"product":"thorsten/phpmyfaq","vendor":"","ecosystem":null,"affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/thorsten/phpMyFAQ/security/advisories/GHSA-6x9g-rfx8-g42q","source_modified_at":"2026-10-03T11:37:10Z","fetched_at":"2026-10-25T18:55:31.805249Z","package":{"ecosystem":"composer","name":"thorsten/phpmyfaq"},"range":"4.1.8"}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/thorsten/phpMyFAQ/security/advisories/GHSA-6x9g-rfx8-g42q","source_modified_at":"2026-10-03T11:37:10Z","fetched_at":"2026-10-25T18:55:31.805249Z","package":{"ecosystem":"composer","name":"thorsten/phpmyfaq"},"version":"4.1.9"}],"cvss":7.1,"severity":"High","kev":{"listed":false},"epss":{"probability":null,"percentile":null,"score_date":null},"published_at":"2026-10-03T11:37:10Z","modified_at":"2026-10-03T11:37:10Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/thorsten/phpMyFAQ/security/advisories/GHSA-6x9g-rfx8-g42q","fetched_at":"2026-10-25T18:55:31.805249Z","source_modified_at":"2026-10-03T11:37:10Z"}],"sources":["GitHub Advisory Database"],"references":[],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":null,"confidence":"unknown","reviewed":false},"change_timestamp":"2026-10-03T11:37:10Z","content_hash":"e76cb7af284ec51c6f7c13380b406381889ffcc88e18835e8bc5f13c712ac140"}}
