{"id":"CVE-2026-42206","aliases":["EUVD-2026-28837","GHSA-3gx8-q682-38mx"],"status":"published","title":"Roadiz OpenID Connect nonce generated but never validated — ID token replay attack","description":"Roadiz is a polymorphic content management system based on a node system. Prior to versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18, the roadiz/openid package generates an OIDC nonce in OAuth2LinkGenerator::generate() and includes it in the authorization request sent to the identity provider, but never stores it and never validates it on the callback. The OpenIdJwtConfigurationFactory validation chain does not include a nonce constraint, and OpenIdAuthenticator::authenticate() never checks the nonce claim in the returned ID token against a stored value. This issue has been patched in versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18.","severity":{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00152,"percentile":0.04444,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-345"],"published":"2026-04-29T20:51:40Z","modified":"2026-10-28T02:30:30Z","fixes":[{"ecosystem":"Packagist","package":"roadiz/openid","fixed_in":["2.7.18","2.6.31","2.5.45","2.3.43"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.7.0"},{"fixed":"2.7.18"}]}]},{"source":"ghsa","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.6.0"},{"fixed":"2.6.31"}]}]},{"source":"ghsa","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.5.0"},{"fixed":"2.5.45"}]}]},{"source":"ghsa","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.3.43"}]}]},{"source":"osv","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.7.0"},{"fixed":"2.7.18"}]}],"versions":["v2.7.0","v2.7.1","v2.7.10","v2.7.11","v2.7.12","v2.7.13","v2.7.14","v2.7.15","v2.7.16","v2.7.17","v2.7.2","v2.7.3","v2.7.4","v2.7.5","v2.7.6","v2.7.7","v2.7.8","v2.7.9"]},{"source":"osv","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.6.0"},{"fixed":"2.6.31"}]}],"versions":["v2.6.0","v2.6.1","v2.6.10","v2.6.11","v2.6.12","v2.6.13","v2.6.14","v2.6.15","v2.6.16","v2.6.17","v2.6.18","v2.6.19","v2.6.2","v2.6.20","v2.6.21","v2.6.22","v2.6.23","v2.6.24","v2.6.25","v2.6.26","v2.6.27","v2.6.28","v2.6.29","v2.6.3","v2.6.30","v2.6.4","v2.6.5","v2.6.6","v2.6.7","v2.6.8","v2.6.9"]},{"source":"osv","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.5.0"},{"fixed":"2.5.45"}]}],"versions":["v2.5.0","v2.5.1","v2.5.10","v2.5.11","v2.5.12","v2.5.13","v2.5.14","v2.5.15","v2.5.16","v2.5.17","v2.5.18","v2.5.19","v2.5.2","v2.5.20","v2.5.21","v2.5.22","v2.5.23","v2.5.24","v2.5.25","v2.5.26","v2.5.27","v2.5.28","v2.5.29","v2.5.3","v2.5.30","v2.5.31","v2.5.32","v2.5.33","v2.5.34","v2.5.35","v2.5.36","v2.5.37","v2.5.38","v2.5.39","v2.5.4","v2.5.40","v2.5.41","v2.5.42","v2.5.43","v2.5.44","v2.5.5","v2.5.6","v2.5.7","v2.5.8","v2.5.9"]},{"source":"osv","ecosystem":"Packagist","package":"roadiz/openid","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.3.43"}]}],"versions":["1.6.0","1.6.1","1.7.0","1.7.1","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","v2.1.0","v2.1.1","v2.1.10","v2.1.11","v2.1.12","v2.1.13","v2.1.14","v2.1.15","v2.1.16","v2.1.17","v2.1.18","v2.1.19","v2.1.2","v2.1.20","v2.1.21","v2.1.22","v2.1.23","v2.1.24","v2.1.25","v2.1.26","v2.1.27","v2.1.28","v2.1.29","v2.1.3","v2.1.30","v2.1.31","v2.1.32","v2.1.33","v2.1.34","v2.1.35","v2.1.36","v2.1.37","v2.1.38","v2.1.39","v2.1.4","v2.1.40","v2.1.41","v2.1.42","v2.1.43","v2.1.44","v2.1.45","v2.1.46","v2.1.47","v2.1.48","v2.1.49","v2.1.5","v2.1.50","v2.1.51","v2.1.52","v2.1.53","v2.1.54","v2.1.55","v2.1.56","v2.1.57","v2.1.6","v2.1.61","v2.1.62","v2.1.63","v2.1.64","v2.1.65","v2.1.66","v2.1.67","v2.1.68","v2.1.69","v2.1.7","v2.1.70","v2.1.71","v2.1.72","v2.1.73","v2.1.74","v2.1.8","v2.1.9","v2.2.0","v2.2.1","v2.2.10","v2.2.11","v2.2.12","v2.2.13","v2.2.14","v2.2.15","v2.2.16","v2.2.17","v2.2.18","v2.2.19","v2.2.2","v2.2.20","v2.2.21","v2.2.22","v2.2.23","v2.2.24","v2.2.25","v2.2.26","v2.2.27","v2.2.28","v2.2.29","v2.2.3","v2.2.30","v2.2.31","v2.2.32","v2.2.4","v2.2.5","v2.2.6","v2.2.7","v2.2.8","v2.2.9","v2.3.0","v2.3.1","v2.3.10","v2.3.11","v2.3.12","v2.3.13","v2.3.14","v2.3.15","v2.3.16","v2.3.17","v2.3.18","v2.3.19","v2.3.2","v2.3.20","v2.3.21","v2.3.22","v2.3.23","v2.3.24","v2.3.25","v2.3.26","v2.3.27","v2.3.28","v2.3.29","v2.3.3","v2.3.30","v2.3.31","v2.3.32","v2.3.33","v2.3.34","v2.3.35","v2.3.36","v2.3.37","v2.3.38","v2.3.39","v2.3.4","v2.3.40","v2.3.41","v2.3.42","v2.3.5","v2.3.6","v2.3.7","v2.3.8","v2.3.9"]}],"products":[{"vendor":"roadiz","product":"core-bundle-dev-app"}],"references":[{"url":"https://github.com/roadiz/core-bundle-dev-app/security/advisories/GHSA-3gx8-q682-38mx","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-42206","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-3gx8-q682-38mx"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/42xxx/CVE-2026-42206.json","tags":["advisory"]},{"url":"https://github.com/roadiz/core-bundle-dev-app","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-42206","title":"Roadiz OpenID Connect nonce generated but never validated — ID token replay attack","description":"Roadiz is a polymorphic content management system based on a node system. Prior to versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18, the roadiz/openid package generates an OIDC nonce in OAuth2LinkGenerator::generate() and includes it in the authorization request sent to the identity provider, but never stores it and never validates it on the callback. The OpenIdJwtConfigurationFactory validation chain does not include a nonce constraint, and OpenIdAuthenticator::authenticate() never checks the nonce claim in the returned ID token against a stored value. This issue has been patched in versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18.","status":"published","published":"2026-05-08T21:54:32.715Z","modified":"2026-05-13T17:47:17.371Z","cvss":[{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","level":"medium","assessor":"cna"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T13:40:35.004553Z"}],"euvd":[{"id":"EUVD-2026-28837","description":"Roadiz is a polymorphic content management system based on a node system. Prior to versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18, the roadiz/openid package generates an OIDC nonce in OAuth2LinkGenerator::generate() and includes it in the authorization request sent to the identity provider, but never stores it and never validates it on the callback. The OpenIdJwtConfigurationFactory validation chain does not include a nonce constraint, and OpenIdAuthenticator::authenticate() never checks the nonce claim in the returned ID token against a stored value. This issue has been patched in versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18.","status":"published","published":"2026-05-08T21:54:32Z","modified":"2026-05-13T17:47:17Z","cvss":[{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","level":"medium"}],"updated_at":"2026-11-02T19:04:33.260537Z"}],"ghsa":[{"id":"GHSA-3gx8-q682-38mx","title":"OpenID Connect nonce generated but never validated — ID token replay attack","description":"### Summary\nThe `roadiz/openid` package generates an OIDC nonce in `OAuth2LinkGenerator::generate()` and includes it in the authorization request sent to the identity provider, but **never stores it** and **never validates it** on the callback. The `OpenIdJwtConfigurationFactory` validation chain does not include a nonce constraint, and `OpenIdAuthenticator::authenticate()` never checks the nonce claim in the returned ID token against a stored value.\n\n### Details\nIn `src/OAuth2LinkGenerator.php`, a nonce is created and sent to the IdP:\n```php\n'nonce' =\u003e $this-\u003etokenGenerator-\u003egenerateToken(),\n```\nHowever, this value is neither stored in session, cache, nor any other persistent store.\n\nIn `src/OpenIdJwtConfigurationFactory.php`, the JWT validation constraints are:\n- `LooseValidAt` (expiry)\n- `PermittedFor` (audience)\n- `IssuedBy` (issuer)\n- `HostedDomain` (optional)\n- `UserInfoEndpoint` (optional)\n\n**No nonce constraint is present.**\n\nIn `src/Authentication/OpenIdAuthenticator.php`, the `authenticate()` method validates the state CSRF token correctly (fixed in v2.7.10), but never retrieves a stored nonce or compares it against the `nonce` claim in the ID token.\n\n### PoC\n1. Obtain a valid ID token from a legitimate OIDC flow for a target user (e.g. via network interception, browser history leak, or referrer header exposure on a non-HTTPS redirect).\n2. Replay the ID token: Since the nonce in the token is never cross-checked against a client-stored value, the token passes all validation constraints as long as it has not expired.\n3. Result: An attacker can authenticate as the victim within the ID token's validity window.\n\nAdditionally, in an authorization code flow with multiple concurrent sessions, a malicious IdP or a compromised token endpoint could inject a token with a mismatched nonce, and the application would accept it silently.\n\n### Impact\n- **ID token replay attacks**: Valid but intercepted tokens can be reused for authentication within their validity period.\n- **Token injection attacks**: A malicious or compromised identity provider can inject tokens across sessions without detection.\n- Affects any Roadiz application using the `roadiz/openid` package with OpenID Connect SSO.\n\nThe OIDC Core 1.0 specification (Section 3.1.3.7) explicitly requires clients to verify the `nonce` claim if it was present in the authorization request.","status":"published","published":"2026-04-29T20:51:40Z","modified":"2026-05-13T13:38:03Z","cvss":[{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","level":"medium"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T14:40:07.01746Z"}],"nvd":[{"id":"CVE-2026-42206","description":"Roadiz is a polymorphic content management system based on a node system. Prior to versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18, the roadiz/openid package generates an OIDC nonce in OAuth2LinkGenerator::generate() and includes it in the authorization request sent to the identity provider, but never stores it and never validates it on the callback. The OpenIdJwtConfigurationFactory validation chain does not include a nonce constraint, and OpenIdAuthenticator::authenticate() never checks the nonce claim in the returned ID token against a stored value. This issue has been patched in versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18.","status":"published","published":"2026-05-08T22:16:31.963Z","modified":"2026-10-26T18:10:00.173Z","cvss":[{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium","assessor":"secondary"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T14:12:18.239974Z"}],"osv":[{"id":"CVE-2026-42206","title":"Roadiz OpenID Connect nonce generated but never validated — ID token replay attack","description":"Roadiz is a polymorphic content management system based on a node system. Prior to versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18, the roadiz/openid package generates an OIDC nonce in OAuth2LinkGenerator::generate() and includes it in the authorization request sent to the identity provider, but never stores it and never validates it on the callback. The OpenIdJwtConfigurationFactory validation chain does not include a nonce constraint, and OpenIdAuthenticator::authenticate() never checks the nonce claim in the returned ID token against a stored value. This issue has been patched in versions 2.3.43, 2.5.45, 2.6.31, and 2.7.18.","status":"published","published":"2026-05-08T21:54:32.715Z","modified":"2026-10-28T02:30:30.124584582Z","cvss":[{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","level":"medium"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T15:45:04.117819Z"},{"id":"GHSA-3gx8-q682-38mx","title":"OpenID Connect nonce generated but never validated — ID token replay attack","description":"### Summary\nThe `roadiz/openid` package generates an OIDC nonce in `OAuth2LinkGenerator::generate()` and includes it in the authorization request sent to the identity provider, but **never stores it** and **never validates it** on the callback. The `OpenIdJwtConfigurationFactory` validation chain does not include a nonce constraint, and `OpenIdAuthenticator::authenticate()` never checks the nonce claim in the returned ID token against a stored value.\n\n### Details\nIn `src/OAuth2LinkGenerator.php`, a nonce is created and sent to the IdP:\n```php\n'nonce' =\u003e $this-\u003etokenGenerator-\u003egenerateToken(),\n```\nHowever, this value is neither stored in session, cache, nor any other persistent store.\n\nIn `src/OpenIdJwtConfigurationFactory.php`, the JWT validation constraints are:\n- `LooseValidAt` (expiry)\n- `PermittedFor` (audience)\n- `IssuedBy` (issuer)\n- `HostedDomain` (optional)\n- `UserInfoEndpoint` (optional)\n\n**No nonce constraint is present.**\n\nIn `src/Authentication/OpenIdAuthenticator.php`, the `authenticate()` method validates the state CSRF token correctly (fixed in v2.7.10), but never retrieves a stored nonce or compares it against the `nonce` claim in the ID token.\n\n### PoC\n1. Obtain a valid ID token from a legitimate OIDC flow for a target user (e.g. via network interception, browser history leak, or referrer header exposure on a non-HTTPS redirect).\n2. Replay the ID token: Since the nonce in the token is never cross-checked against a client-stored value, the token passes all validation constraints as long as it has not expired.\n3. Result: An attacker can authenticate as the victim within the ID token's validity window.\n\nAdditionally, in an authorization code flow with multiple concurrent sessions, a malicious IdP or a compromised token endpoint could inject a token with a mismatched nonce, and the application would accept it silently.\n\n### Impact\n- **ID token replay attacks**: Valid but intercepted tokens can be reused for authentication within their validity period.\n- **Token injection attacks**: A malicious or compromised identity provider can inject tokens across sessions without detection.\n- Affects any Roadiz application using the `roadiz/openid` package with OpenID Connect SSO.\n\nThe OIDC Core 1.0 specification (Section 3.1.3.7) explicitly requires clients to verify the `nonce` claim if it was present in the authorization request.","status":"published","published":"2026-04-29T20:51:40Z","modified":"2026-05-13T13:55:48.291155Z","cvss":[{"version":"4.0","score":5.7,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P","level":"medium"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T15:46:35.747385Z"}]}}
