{"id":"GHSA-3gx8-q682-38mx","summary":"OpenID Connect nonce generated but never validated — ID token replay attack","details":"### 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.","aliases":["CVE-2026-42206"],"modified":"2026-05-13T13:55:48.291155Z","published":"2026-04-29T20:51:40Z","database_specific":{"nvd_published_at":"2026-05-08T22:16:31Z","cwe_ids":["CWE-345"],"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-04-29T20:51:40Z"},"references":[{"type":"WEB","url":"https://github.com/roadiz/core-bundle-dev-app/security/advisories/GHSA-3gx8-q682-38mx"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-42206"},{"type":"PACKAGE","url":"https://github.com/roadiz/core-bundle-dev-app"}],"affected":[{"package":{"name":"roadiz/openid","ecosystem":"Packagist","purl":"pkg:composer/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"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-3gx8-q682-38mx/GHSA-3gx8-q682-38mx.json"}},{"package":{"name":"roadiz/openid","ecosystem":"Packagist","purl":"pkg:composer/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"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-3gx8-q682-38mx/GHSA-3gx8-q682-38mx.json"}},{"package":{"name":"roadiz/openid","ecosystem":"Packagist","purl":"pkg:composer/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"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-3gx8-q682-38mx/GHSA-3gx8-q682-38mx.json"}},{"package":{"name":"roadiz/openid","ecosystem":"Packagist","purl":"pkg:composer/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"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-3gx8-q682-38mx/GHSA-3gx8-q682-38mx.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"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"}]}