{"record":{"id":"63700cfe42ac0078","repo":"passbolt/passbolt_api","slug":"only-guests-are-allowed-to-start-setup","errorCode":null,"errorMessage":"Only guests are allowed to start setup.","messagePattern":"Only guests are allowed to start setup\\.","errorType":"exception","errorClass":"Cake\\Http\\Exception\\ForbiddenException","httpStatus":403,"severity":"error","filePath":"src/Controller/Setup/SetupStartController.php","lineNumber":57,"sourceCode":"        parent::beforeFilter($event);\n    }\n\n    /**\n     * Setup start\n     *\n     * @param \\App\\Service\\Setup\\AbstractSetupStartService $infoService info service\n     * @param string $userId uuid of the user\n     * @param string $token uuid of the token\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the token is missing or not a uuid\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the user id is missing or not a uuid\n     */\n    public function start(AbstractSetupStartService $infoService, string $userId, string $token): void\n    {\n        if ($this->request->is('json')) {\n            // Do not allow logged in user to start setup\n            if ($this->User->role() !== Role::GUEST) {\n                throw new ForbiddenException(__('Only guests are allowed to start setup.'));\n            }\n            $data = $infoService->getInfo($userId, $token);\n            $this->success(__('The operation was successful.'), $data);\n        } else {\n            $this->set('title', Configure::read('passbolt.meta.description'));\n        }\n    }\n}\n","sourceCodeStart":39,"sourceCodeEnd":66,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Controller/Setup/SetupStartController.php#L39-L66","documentation":"Thrown by SetupStartController::start when a JSON API request to begin an account setup arrives from an authenticated user whose role is not GUEST. The setup flow (recover or complete) is reserved for guests — users who have not finished registration. Any other role (admin, user) is refused before the setup start service is invoked.","triggerScenarios":"Calling GET/POST /setup/start/<userId>/<token> while authenticated as an ADMIN or USER role, e.g. an admin testing the setup link in the same browser session as their logged-in account.","commonSituations":"Admin clicks a user's setup invitation link while logged in; QA replaying setup URLs with an authenticated session cookie; a user trying to recover their own account using the guest-only setup endpoint.","solutions":["Log out (or use a private/incognito window) before opening the setup link so the request carries no non-guest session.","If an admin must trigger setup for a user, have the user open the link in their own unauthenticated session.","If you control the client, strip the session/auth header for this request."],"exampleFix":"// before (admin session cookie sent with request)\nfetch('/setup/start/' + userId + '/' + token, { credentials: 'include' });\n// after\nfetch('/setup/start/' + userId + '/' + token, { credentials: 'omit' }); // or use an incognito session","handlingStrategy":"validation","validationCode":"// ensure no privileged session is attached before starting setup\nif (session?.role && session.role !== 'guest') {\n  throw new Error('Logout required: setup can only be started by guests');\n}","typeGuard":"function isGuest(session) { return typeof session?.role === 'string' && session.role === 'guest'; }","tryCatchPattern":"try { await startSetup(userId, token); } catch (e) { if (e.status === 403 && /Only guests/.test(e.message)) { logout(); retryInIncognito(); } else throw e; }","preventionTips":["Open setup/recover links in incognito or a logged-out profile","Never send auth cookies/headers with setup endpoints","Test setup flows with a fresh browser context"],"tags":["authorization","setup","forbidden","roles"],"backgroundTag":"insufficient-permissions","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"}