- A GitHub advisory says TinaCMS's tina-markdown component puts link addresses into pages unchecked, so a javascript: link authored in the CMS runs script when a visitor clicks it.
- It matters because a person who can only edit content gains script access in visitors' browsers, and a clicking editor or admin can expose their login token.
- Ask your team whether you use @tinacms/web-components, confirm the version, and check that every content renderer applies the same link checks.
A security control is only as strong as the one place it was forgotten. A new advisory shows how that happens inside a content management system, and why the person who types into a text box can become a threat to your visitors.
What the advisory says
The GitHub Advisory Database published GHSA-c42q-qvc3-j6vg on October 9, 2026. It covers `<tina-markdown>`, a component in the @tinacms/web-components package. The component turns rich text from the TinaCMS content system into a web page.
The advisory says it copies each link's address straight into the page with no check on the address type. A link written in the CMS as `javascript:…` becomes a live link. When a visitor clicks it, the attacker's script runs inside the site's own origin. The reporter is credited as iaohkut-from-NightWolf-Team.
The advisory text lists no CVE ID. It does include a working proof of concept.
How the flaw works
Rich text is stored as a structured tree of pieces: paragraphs, bold runs, links. The component walks that tree and builds page elements. For a link, it takes the stored address and assigns it to the anchor's `href` attribute.
Browsers treat a `javascript:` address as a command, not a destination. Clicking it runs code. That is why web software must check the start of every address before using it.
The component does run a cleaner, DOMPurify, but only on raw HTML pieces. The advisory says that call returns before the link branch is reached, so link addresses are never inspected. The researcher showed the gap directly. A `javascript:` link hidden in raw HTML was stripped. The same link sent as a link piece was not.
The component also uses an open shadow root. That is a browser feature that fences off page styling. The advisory notes it gives no protection against script.
The fix already existed in the building
The repository has a helper called `sanitizeUrl`. The advisory says the React and Astro renderers both call it. The researcher ran it on the same kind of input and it returned an empty string, rejecting the address.
So the defect is a missing call, not a missing tool. The advisory also reads this as an oversight. A changelog entry for version 0.2.0 states a goal of "matching the components prop on the React and Astro renderers". The existing test checks only that a normal https link works. No test tries a dangerous address.
The lesson here is that safe handling of untrusted input is a habit, not a property of a system. Each new renderer must remember it again. The one built for sites outside React is the one that forgot. The advisory notes that these are the sites that do not get the sanitized React renderer.
The second line, the image source, does not run script from a `javascript:` address. The advisory therefore does not score it. It still lacks validation.
Why an editor's pen becomes a risk
Many organisations treat content editors as trusted. This flaw shows why that trust has a cost. According to the advisory, a user whose only power is editing content can gain script execution in every visitor's browser on the site.
The worst case involves the admin tools. The advisory points to the documented TinaCMS setup, which places the admin area on the same origin as the public pages. It also keeps the editor's login token in the browser's localStorage under `tinacms-auth`. In the proof of concept, the injected script read that token.
There are limits. A visitor must click the link. The token is exposed only if the person who clicks is an editor or administrator. The test ran on a local loopback server with Chrome, and no outside traffic was sent. The advisory also does not say any site has been attacked.
What to ask your team
First, ask whether any site uses `@tinacms/web-components` or `<tina-markdown>`. The advisory links to the 0.2.1 release. Ask your team to confirm that this release contains the fix before relying on it.
Second, ask who can edit rich-text content and whether those accounts are treated as a security boundary. Third, ask whether your admin tools share an origin with your public site. Separating them limits what a single injected script can reach.
Last, ask for a short audit of every place your own code turns stored content into links or images. If six places check and one does not, the fault lies in the process that let the gap exist. The advisory's suggested remedy is a call to an existing helper, but finding the place that lacks it is the work.
Produced by the WebPulse Newsroom with AI assistance from the original reporting credited below, and checked against that source by our editorial review. How we use AI.
Original reporting: GitHub Advisory Database.





