Preface
Due to the russian war on Ukraine, we are much less active on this blog and social media. However, some events make us hit the dust off the keyboard and share some information. For instance, a vulnerability is worth a CVE. We found this one in February 2022, and a few others are under review. Meanwhile, all BSG team members are safe, and we stay operational.
Introduction
Tagify is a tags input component for React, Vue, and Angular that can also be used as a standalone library in pure JavaScript. It transforms an input field or a textarea into a Tags component.
Tagify resources and project homepage:
- https://yaireo.github.io/tagify/
- https://github.com/yairEO/tagify
- https://www.npmjs.com/package/@yaireo/tagify
Summary
A Cross-site Scripting (XSS) issue was discovered in @yaireo/tagify versions before 4.9.8 (CVE-2022-25854). An attacker could exploit it by storing persistent scripts, which would lead to arbitrary code execution when visiting an affected page.
Impact
Tagify is a quite popular JavaScript library: there are 38 000 weekly downloads on npm and 24 packages depending on @yaireo/tagify.
Technical Summary
While testing custom inputs functionality on a website, we observed that the “tags” parameter was not sanitized against cross-site scripting attacks when loading the data via the user’s profile page.
Deep dive into the code base showed that the bug is in Tagify’s template wrapper, leading to an XSS vulnerability, making applications that use tagify.js or react.tagify vulnerable as well.
Affected Code
data-placeholder="${_s.placeholder || '​'}"
aria-placeholder="${_s.placeholder || ''}"
Example on Codesandbox: https://codesandbox.io/s/tagify-react-wrapper-forked-lgs3er?file=/src/CrazyTags.jsx:392-443
Tagify’s API does not provide any documented options to add onhover, onclick, etc., handlers using the placeholder prop. There is no way to add the handlers using any other props described in the TagifyWrapper.propTypes object, except placeholder. It is undocumented, unintended, and unexpected behavior.
Pull request
https://github.com/yairEO/tagify/commit/198c0451fad188390390395ccfc84ab371def4c7
Disclosure Timeline
- 2022-02-11 Bug discovered.
- 2022-02-15 Found the source of the bug.
- 2022-02-15 Created PoC.
- 2022-02-16 Disclosure to vendor.
- 2022-02-16 Pull Request with the fix was sent to the vendor.
- 2022-02-17 Vendor informed us that it would be fixed with the following product version (v4.9.8).
- 2022-02-17 Vendor published a fixed product version (v4.9.8).
Proof of Concept
- Open the following forked Tagify’s React Wrapper demo.
- Notice line #17, where a customUserInput variable is declared. This variable mocks data that came from an API or an input.
- On line #23, we use the customUserInput variable to customize tags.
- Open the Tags tab once the demo app is rendered and hover on the first input. It will fire the XSS.
Solution
As of the date of this publication, all versions above 4.9.8 are safe to use.
Credits
The BSG team: Roman Rott, Serhii Korolenko, Ihor Bliumental, and Maksym Khramov.