{"id":"GHSA-w67g-2h6v-vjgq","summary":"Phlex XSS protection bypass via attribute splatting, dynamic tags, and href values","details":"### Impact\n\nDuring a security audit conducted with Claude Opus 4.6 and GPT-5.3-Codex, we identified three specific ways to bypass the XSS (cross-site-scripting) protection built into Phlex.\n\n1. The first bypass could happen if user-provided attributes with string keys were splatted into HTML tag, e.g. `div(**user_attributes)`.\n2. The second bypass could happen if user-provided tag names were passed to the `tag` method, e.g. `tag(some_tag_name_from_user)`.\n3. The third bypass could happen if user’s links were passed to `href` attributes, e.g. `a(href: user_provided_link)`.\n\nAll three of these patterns are meant to be safe and all have now been patched.\n\n### Patches\n\nPhlex has patched all three issues and introduced new tests that run against Safari, Firefox and Chrome.\n\nThe patched versions are:\n\n- [2.4.1](https://rubygems.org/gems/phlex/versions/2.4.1)\n- [2.3.2](https://rubygems.org/gems/phlex/versions/2.3.2)\n- [2.2.2](https://rubygems.org/gems/phlex/versions/2.2.2)\n- [2.1.3](https://rubygems.org/gems/phlex/versions/2.1.3)\n- [2.0.2](https://rubygems.org/gems/phlex/versions/2.0.3)\n- [1.11.1](https://rubygems.org/gems/phlex/versions/1.11.1)\n\nPhlex has also patched the [`main`](https://github.com/yippee-fun/phlex) branch in GitHub.\n\n### Workarounds\nIf a project uses a secure CSP (content security policy) or if the application doesn’t use any of the above patterns, it is not at risk.","modified":"2026-02-06T20:58:00.573179Z","published":"2026-02-06T19:35:09Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-02-06T19:35:09Z","nvd_published_at":null,"cwe_ids":["CWE-79"]},"references":[{"type":"WEB","url":"https://github.com/yippee-fun/phlex/security/advisories/GHSA-w67g-2h6v-vjgq"},{"type":"WEB","url":"https://github.com/yippee-fun/phlex/commit/1d85da417cb15eb8cb2f54a68d531c9b35d9d03a"},{"type":"WEB","url":"https://github.com/yippee-fun/phlex/commit/556441d5a64ff93f749e8116a05b2d97264468ee"},{"type":"WEB","url":"https://github.com/yippee-fun/phlex/commit/74e3d8610ffabc2cf5f241945e9df4b14dceb97d"},{"type":"WEB","url":"https://github.com/yippee-fun/phlex/commit/9f56ad13bea9a7d6117fdfd510446c890709eeac"},{"type":"WEB","url":"https://github.com/yippee-fun/phlex/commit/fe9ea708672f9fa42526d9b47e1cdc4634860ef1"},{"type":"PACKAGE","url":"https://github.com/yippee-fun/phlex"}],"affected":[{"package":{"name":"phlex","ecosystem":"RubyGems","purl":"pkg:gem/phlex"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.4.0.beta1"},{"fixed":"2.4.1"}]}],"versions":["2.4.0","2.4.0.beta1","2.4.0.beta2"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-w67g-2h6v-vjgq/GHSA-w67g-2h6v-vjgq.json"}},{"package":{"name":"phlex","ecosystem":"RubyGems","purl":"pkg:gem/phlex"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.0"},{"fixed":"2.3.2"}]}],"versions":["2.3.0","2.3.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-w67g-2h6v-vjgq/GHSA-w67g-2h6v-vjgq.json"}},{"package":{"name":"phlex","ecosystem":"RubyGems","purl":"pkg:gem/phlex"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.2.0"},{"fixed":"2.2.2"}]}],"versions":["2.2.0","2.2.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-w67g-2h6v-vjgq/GHSA-w67g-2h6v-vjgq.json"}},{"package":{"name":"phlex","ecosystem":"RubyGems","purl":"pkg:gem/phlex"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.1.0"},{"fixed":"2.1.3"}]}],"versions":["2.1.0","2.1.1","2.1.2"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-w67g-2h6v-vjgq/GHSA-w67g-2h6v-vjgq.json"}},{"package":{"name":"phlex","ecosystem":"RubyGems","purl":"pkg:gem/phlex"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0.beta1"},{"fixed":"2.0.2"}]}],"versions":["2.0.0","2.0.0.beta1","2.0.0.beta2","2.0.0.rc1","2.0.0.rc2","2.0.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-w67g-2h6v-vjgq/GHSA-w67g-2h6v-vjgq.json"}},{"package":{"name":"phlex","ecosystem":"RubyGems","purl":"pkg:gem/phlex"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.11.1"}]}],"versions":["0.1.0","0.2.0","0.2.1","0.2.2","0.3.0","0.3.1","0.3.2","0.4.0","0.5.0","0.5.1","0.5.2","0.5.3","1.0.0","1.0.0.rc1","1.0.0.rc2","1.0.1","1.1.0","1.1.1","1.10.0","1.10.1","1.10.2","1.10.3","1.11.0","1.2.0","1.2.1","1.2.2","1.3.0","1.3.1","1.3.2","1.3.3","1.4.0","1.4.1","1.4.2","1.5.0","1.5.1","1.5.2","1.5.3","1.6.0","1.6.1","1.6.2","1.6.3","1.7.0","1.7.1","1.7.2","1.8.0","1.8.1","1.8.2","1.8.3","1.9.0","1.9.1","1.9.2","1.9.3"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/02/GHSA-w67g-2h6v-vjgq/GHSA-w67g-2h6v-vjgq.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N"}]}