{"record":{"id":"bee9f532719701fc","repo":"passbolt/passbolt_api","slug":"the-authentication-token-should-be-a-valid-uuid-bee9f5","errorCode":null,"errorMessage":"The authentication token should be a valid UUID.","messagePattern":"The authentication token should be a valid UUID\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoStateCookieService.php","lineNumber":55,"sourceCode":"\n    /**\n     * Passbolt temporary cookie expiry in minutes\n     *\n     * @var int\n     */\n    public const MFA_COOKIE_DUO_STATE_EXPIRY_IN_MINUTES = 10;\n\n    /**\n     * Create a Duo state cookie.\n     *\n     * @param string $token Authentication token's token\n     * @param bool $secure Whether to set the cookie as secure\n     * @return \\Cake\\Http\\Cookie\\Cookie The created cookie containing the Duo state value\n     */\n    public function createDuoStateCookie(string $token, bool $secure): Cookie\n    {\n        if (!Validation::uuid($token)) {\n            throw new InvalidArgumentException('The authentication token should be a valid UUID.');\n        }\n\n        return (new Cookie(self::MFA_COOKIE_DUO_STATE))\n            ->withValue($token)\n            ->withPath('/')\n            ->withHttpOnly(true)\n            ->withSecure($secure)\n            ->withExpiry((new DateTime())->addMinutes(self::MFA_COOKIE_DUO_STATE_EXPIRY_IN_MINUTES));\n    }\n\n    /**\n     * Read the Duo state cookie.\n     *\n     * @param \\Cake\\Http\\ServerRequest $request Server request\n     * @return array|string|null The cookie value\n     */\n    public function readDuoStateCookieValue(ServerRequest $request): array|string|null\n    {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoStateCookieService.php#L37-L73","documentation":"MfaDuoStateCookieService::createDuoStateCookie() stores the mfa authentication token id (Duo state) in an HttpOnly secure cookie. It validates the token is a UUID and throws an InvalidArgumentException otherwise, so a corrupt state cookie is never emitted.","triggerScenarios":"Calling createDuoStateCookie($token, $secure) with a token that is not a valid UUID — empty string, truncated id, or a non-token value.","commonSituations":"Custom controllers passing a session key instead of the AuthenticationToken id; token value taken from a mangled query parameter; test code passing placeholder strings.","solutions":["Pass the generated AuthenticationToken id (UUID) from the Duo start flow","Validate with Validation::uuid($token) before calling","Ensure the value comes from the token object, not user-controlled input"],"exampleFix":"// before\n$cookieService->createDuoStateCookie($this->request->getQuery('state'), true);\n// after\n$token = $authenticationToken->id; // valid UUID from generate()\n$cookieService->createDuoStateCookie($token, true);","handlingStrategy":"validation","validationCode":"use Cake\\Validation\\Validation;\nif (!is_string($token) || !Validation::uuid($token)) { throw new \\InvalidArgumentException('token must be a UUID'); }","typeGuard":"function isUuid(mixed $v): bool { return is_string($v) && (bool)preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $v); }","tryCatchPattern":"try { $cookie = $cookieService->createDuoStateCookie($token, $secure); } catch (\\InvalidArgumentException $e) { /* return 400; token must come from start() */ }","preventionTips":["Source the cookie value from the AuthenticationToken entity id only","Never seed the state cookie from user-controlled input"],"tags":["mfa","duo","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"}