Tagify XSS

CVE-2022-25854: Stored XSS in @yaireo/tagify npm module


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.


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 example.
A Tagify example.

Tagify resources and project homepage:


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.


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.

XSS example.
The XSS example.

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


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

  1. Open the following forked Tagify’s React Wrapper demo.
  2. Notice line #17, where a customUserInput variable is declared. This variable mocks data that came from an API or an input.
  3. On line #23, we use the customUserInput variable to customize tags.
  4. Open the Tags tab once the demo app is rendered and hover on the first input. It will fire the XSS.
XSS Proof of Concept
The XSS Proof of Concept.


As of the date of this publication, all versions above 4.9.8 are safe to use.


The BSG team: Roman Rott, Serhii Korolenko, Ihor Bliumental, and Maksym Khramov.

Leave a Comment