{"record":{"id":"d8cf40e2b9de546f","repo":"passbolt/passbolt_api","slug":"the-duo-state-cookie-should-be-a-valid-uuid","errorCode":null,"errorMessage":"The Duo state cookie should be a valid UUID.","messagePattern":"The Duo state cookie should be a valid UUID\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Controller/Duo/DuoSetupCallbackGetController.php","lineNumber":196,"sourceCode":"     *\n     * @return string The token id stored in the cookie\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the cookie is not defined\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the cookie value is not a string\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the cookie value is not a valid uuid\n     */\n    private function consumeAndAssertCookieToken(): string\n    {\n        $cookieToken = (new MfaDuoStateCookieService())->readDuoStateCookieValue($this->getRequest());\n        if (is_null($cookieToken)) {\n            throw new BadRequestException(__('A Duo state cookie is required.'));\n        }\n        $cookieToExpire = new Cookie(MfaDuoStateCookieService::MFA_COOKIE_DUO_STATE);\n        $this->setResponse($this->getResponse()->withExpiredCookie($cookieToExpire));\n\n        if (!is_string($cookieToken)) {\n            throw new BadRequestException(__('The Duo state cookie value should be a string.'));\n        } elseif (!Validation::uuid($cookieToken)) {\n            throw new BadRequestException(__('The Duo state cookie should be a valid UUID.'));\n        }\n\n        return $cookieToken;\n    }\n\n    /**\n     * Add to the response the MFA verified cookie.\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac User access control\n     * @param \\App\\Authenticator\\SessionIdentificationServiceInterface $sessionIdentificationService session ID service\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException if it cannot create MFA cookie\n     */\n    private function addMfaVerifiedCookieToResponse(\n        UserAccessControl $uac,\n        SessionIdentificationServiceInterface $sessionIdentificationService\n    ): void {\n        try {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Controller/Duo/DuoSetupCallbackGetController.php#L178-L214","documentation":"Thrown by DuoSetupCallbackGetController::consumeAndAssertCookieToken when the Duo state cookie value is a string but fails Cake's Validation::uuid() check. The state token is generated as a UUID and must round-trip unchanged; any corruption or forgery is rejected.","triggerScenarios":"GET /mfa/duo/setup/callback with a state cookie containing a non-UUID string: truncated value, URL-encoded/decoded variant, hand-crafted value, or value from an unrelated cookie.","commonSituations":"Cookie truncated by intermediary proxies with header size limits; manual cookie manipulation during debugging; copy-pasted callback URLs with altered cookie values; old cookies left from a differently formatted flow.","solutions":["Clear the MFA Duo cookies and restart the Duo setup flow to get a fresh UUID state cookie.","Check no proxy or middleware truncates or encodes the Cookie header.","Do not manually set or edit passbolt MFA cookies; let the server generate them.","If reproducible, verify Validation::uuid() format expectations against the cookie value logged in the request."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const uuidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nif (!uuidRe.test(cookies.passbolt_mfa_duo_state ?? '')) { throw new Error('Duo state cookie is not a valid UUID; restart flow.'); }","typeGuard":"function isValidUuid(value: unknown): value is string {\n  return typeof value === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}","tryCatchPattern":"try {\n  await callbackDuoSetup();\n} catch (e) {\n  if (e.status === 400 && /valid UUID/.test(e.message)) {\n    clearMfaCookies(); restartDuoSetupFlow();\n  } else { throw e; }\n}","preventionTips":["Restart the flow instead of reusing or hand-editing state cookies.","Check intermediaries do not truncate the Cookie header.","Verify cookie values survive URL round-trips without being mangled.","Log the cookie value when debugging to spot corruption early."],"tags":["duo","mfa","cookie","uuid","validation"],"backgroundTag":"invalid-identifier-format","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"}