{"record":{"id":"14ab9fed9464d3aa","repo":"passbolt/passbolt_api","slug":"healthcheck-security-index-endpoint-disabled","errorCode":null,"errorMessage":"Healthcheck security index endpoint disabled.","messagePattern":"Healthcheck security index endpoint disabled\\.","errorType":"exception","errorClass":"ForbiddenException","httpStatus":403,"severity":"warning","filePath":"src/Controller/Healthcheck/HealthcheckIndexController.php","lineNumber":120,"sourceCode":"                ->setLayout('login')\n                ->setTemplatePath('Healthcheck')\n                ->setTemplate('index');\n            $this->success(__('All checks ran successfully!'), $body);\n        } else {\n            $healthcheckResult = $this->formatCollectionResponseAsPerLegacy($resultsGroupByDomain);\n\n            $this->success(__('The operation was successful.'), $healthcheckResult);\n        }\n    }\n\n    /**\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\ForbiddenException if the endpoint is deactivated\n     */\n    private function throwErrorIsEndpointIsDisabled(): void\n    {\n        if (!Configure::read(self::PASSBOLT_PLUGINS_HEALTHCHECK_SECURITY_INDEX_ENDPOINT_ENABLED)) {\n            throw new ForbiddenException(__('Healthcheck security index endpoint disabled.'));\n        }\n    }\n\n    /**\n     * @return array\n     */\n    private function getDomainsIgnore(): array\n    {\n        return [HealthcheckServiceCollector::DOMAIN_JWT];\n    }\n\n    /**\n     * Formats given collection as per legacy array structure. This helps us keep backward compatibility.\n     *\n     * @deprecated As of v4.7.0, this is just to keep backward compatibility.\n     * @param \\Cake\\Collection\\CollectionInterface $resultsGroupByDomain Result collection to format as per legacy array format.\n     * @return array\n     */","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Controller/Healthcheck/HealthcheckIndexController.php#L102-L138","documentation":"Passbolt throws this 403 when the healthcheck security index endpoint has been disabled via the config flag PASSBOLT_PLUGINS_HEALTHCHECK_SECURITY_INDEX_ENDPOINT_ENABLED. throwErrorIsEndpointIsDisabled runs in beforeFilter so the request never reaches the action.","triggerScenarios":"Calling GET /healthcheck/security-index (or the healthcheck UI requesting it) while the flag is set to false in config (e.g. passbolt.plugins.healthcheckSecurityIndexEndpoint.enabled = false).","commonSituations":"Operators hardening production by disabling detailed healthcheck exposure, then their monitoring scripts still probe the endpoint; config migration dropping the flag default; copy of production config used locally with the endpoint off.","solutions":["Set the flag to true in config: Configure::write('passbolt.plugins.healthcheckSecurityIndexEndpoint.enabled', true) or in config/passbolt.php","If the endpoint was disabled intentionally on purpose, update monitoring scripts to use the main /healthcheck.json instead","Check app/config for an environment-specific file disabling the plugin endpoint","Restart/clear cache after config change (cake cache clear_all) so Configure picks it up"],"exampleFix":"// before (config/passbolt.php)\n'healthcheckSecurityIndexEndpoint' => ['enabled' => false],\n// after\n'healthcheckSecurityIndexEndpoint' => ['enabled' => true],","handlingStrategy":"fallback","validationCode":"const enabled = await serverConfig('passbolt.plugins.healthcheckSecurityIndexEndpoint.enabled');\nif (!enabled) return runBasicHealthcheckOnly();","typeGuard":"null","tryCatchPattern":"try {\n  return await fetchSecurityIndexHealthcheck();\n} catch (e) {\n  if (e.status === 403) return fetch('/healthcheck.json').then(r=>r.json()); // fallback to main healthcheck\n  throw e;\n}","preventionTips":["Detect the flag in server config before probing security-index endpoint","Fall back to the aggregate /healthcheck.json endpoint","Coordinate monitoring scripts with ops hardening decisions"],"tags":["http-403","feature-flag","healthcheck","config"],"backgroundTag":"feature-not-enabled","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}