View Issue Details

IDProjectCategoryView StatusLast Update
0036973mantisbtsecuritypublic2026-03-23 13:23
Reporterninjasec Assigned Todregad  
PriorityhighSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version1.3.8 
Target Version2.28.1Fixed in Version2.28.1 
Summary0036973: CVE-2026-33548: Stored HTML Injection / XSS in my_view_page.php Timeline via Unescaped Historic Tag Name
Description

MantisBT’s timeline renderer inserts historic tag names into HTML without escaping when the old tag name no longer resolves to an existing tag row.

The vulnerable path is in IssueTagTimelineEvent.class.php:64. For tag timeline events, the renderer attempts to resolve the historic tag name with tag_get_by_name(). If that lookup succeeds, it uses the safe tag_get_link() path. If it fails, it falls back to outputting the historic tag name directly inside the timeline HTML.

Because tag names can contain HTML, an attacker can create a tag with markup, attach it to an issue, then rename or otherwise change it so the original historic name no longer resolves. When a victim later loads my_view_page.php, the timeline entry renders the attacker-controlled historic tag name as raw HTML inside <span class="tag_name">...</span>.

Steps To Reproduce

Steps:

  1. Log in as a user allowed to create and attach tags, e.g. reporter.
  2. Create a tag with a harmless HTML payload such as:
    <h1>timeline-poc</h1>
  3. Attach the tag to an issue.
  4. Rename the tag to a different name, or delete it, so the historic tag name no longer matches a current tag row.
  5. Visit my_view_page.php.
  6. Observe the timeline entry for the older tag action.
TagsNo tags attached.

Relationships

related to 0036971 closeddregad CVE-2026-33517: Stored HTML Injection / XSS in Tag Delete Confirmation via Unescaped Tag Name 

Activities

ninjasec

ninjasec

2026-03-16 07:20

reporter   ~0070883

Reported issue is related to https://mantisbt.org/bugs/view.php?id=36971

dregad

dregad

2026-03-16 07:54

developer   ~0070885

Issue processed as part of https://github.com/mantisbt/mantisbt/security/advisories/GHSA-fh48-f69w-7vmp and covered by the same CVE ID as 0036971 (not yet assigned).

dregad

dregad

2026-03-16 08:29

developer   ~0070886

Posting the (slightly redacted) Matrix chat with @ninjasec for the record.


Mon, Mar 16, 2026, 11:34:55 - ninjasec: Hey, That was an quick patch.
Regarding, my comment on github pr https://github.com/mantisbt/mantisbt-ghsa-fh48-f69w-7vmp/pull/1. I believe, I cause an confusion.
Could you help me verify for timeline xss once again ?
Mon, Mar 16, 2026, 11:42:14 - dregad: Sure give me 5 minutes I'm not in front of my laptop right now
Mon, Mar 16, 2026, 11:44:21 - ninjasec: No worries.
Steps to reproduce:
Create an issue with tag <h1>timeline</h1>. Then goto Update tag and update it <h1>timeline-poc</h1> and save it. If you visit homepage again, now it should be injected.
Mon, Mar 16, 2026, 11:45:57 - dregad: OK I'm trying now
Mon, Mar 16, 2026, 11:49:07 - dregad: OK I get it
Mon, Mar 16, 2026, 11:50:15 - ninjasec: Great!. I believe as it is an different path. Should i create an new issue ?
Mon, Mar 16, 2026, 11:50:34 - dregad: I'm looking at the code now, give me a moment
Mon, Mar 16, 2026, 11:53:09 - ninjasec: https://github.com/mantisbt/mantisbt/blob/master/core/classes/IssueTagTimelineEvent.class.php#L64 i believe this is the vulnerable code.
Mon, Mar 16, 2026, 12:03:31 - dregad: Indeed
Mon, Mar 16, 2026, 12:04:38 - dregad: And I think I get it - the injection occurs when tag_get_by_name() does not find the tag, and displays the name as fallback
Mon, Mar 16, 2026, 12:05:12 - dregad: Because it gets it from history
Mon, Mar 16, 2026, 12:05:34 - dregad: Indeed it's a different issue so feel free to open it
Mon, Mar 16, 2026, 12:05:59 - dregad: but IMO it's the same vulnerability so I would fix both under the same CVE
Mon, Mar 16, 2026, 12:06:21 - dregad: Just reword the advisory
Mon, Mar 16, 2026, 12:06:31 - dregad: Do you agree ?
Mon, Mar 16, 2026, 12:10:23 - dregad: This is the patch

diff --git a/core/classes/IssueTagTimelineEvent.class.php b/core/classes/IssueTagTimelineEvent.class.php
index 01b5754fa..c2aa590da 100644
--- a/core/classes/IssueTagTimelineEvent.class.php
+++ b/core/classes/IssueTagTimelineEvent.class.php
@@ -61,7 +61,7 @@ class IssueTagTimelineEvent extends TimelineEvent {
                                $t_string,
                                prepare_user_name( $this->user_id ),
                                string_get_bug_view_link( $this->issue_id ),
-                               $t_tag_row ? tag_get_link( $t_tag_row ) : $this->tag_name
+                               $t_tag_row ? tag_get_link( $t_tag_row ) : string_html_specialchars( $this->tag_name )
                        )
                        . '</div>';
                $t_html .= $this->html_end();

Mon, Mar 16, 2026, 12:11:07 - ninjasec: I guess, yes it should work as both are related to get_tag_name
Mon, Mar 16, 2026, 12:15:56 - ninjasec sent an image. (Media omitted)
Mon, Mar 16, 2026, 12:16:00 - ninjasec: Fix works!
Mon, Mar 16, 2026, 12:16:20 - dregad: Thanks for confirming
Mon, Mar 16, 2026, 12:16:28 - dregad: I'll push an additional commit
Mon, Mar 16, 2026, 12:17:01 - dregad: Are you opening a separate Issue on our tracker ?
Mon, Mar 16, 2026, 12:18:56 - ninjasec: Yes done
Mon, Mar 16, 2026, 12:19:06 - ninjasec: https://mantisbt.org/bugs/view.php?id=36973
Mon, Mar 16, 2026, 12:20:33 - dregad: Bug exists since 1.3.0 (df320f05553b4c2ba44d7b23f5c7f80ca6d88bd4)
Mon, Mar 16, 2026, 12:22:27 - ninjasec: Seems from a long time
Mon, Mar 16, 2026, 12:25:31 - dregad: Yep. Actually the original commit is 1f7b13f06b22e46fcda3a2e7226278b1eaaea623 - from the very introduction of Timeline in 1.3 beta
Mon, Mar 16, 2026, 12:27:07 - dregad: https://github.com/mantisbt/mantisbt/blob/1f7b13f06b22e46fcda3a2e7226278b1eaaea623/core/timeline_inc.php#L143
Mon, Mar 16, 2026, 12:29:26 - dregad: That was a nice catch
Mon, Mar 16, 2026, 12:29:27 - dregad: Thanks !
Mon, Mar 16, 2026, 12:29:46 - ninjasec: No problem!
Mon, Mar 16, 2026, 12:43:36 - ninjasec: By the way, you were incredibly responsive and patched it quickly, that was a great experience! It's not always the case, so I really appreciate the fast turnaround and clear communication.
Mon, Mar 16, 2026, 12:44:15 - dregad: I always try my best to treat security issues as a priority
Mon, Mar 16, 2026, 12:44:37 - dregad: But you were quite lucky as I was fully available at the right time - it's not always that quick �
Mon, Mar 16, 2026, 12:48:05 - ninjasec: Really appreciate you prioritizing security, makes all the difference.
Will bother you again if I find anything! Have a nice week!
Thanks again!
Mon, Mar 16, 2026, 12:48:25 - dregad: Please do
Mon, Mar 16, 2026, 12:48:27 - dregad: Thank you

dregad

dregad

2026-03-21 19:33

developer   ~0070900

Issue processed as part of https://github.com/mantisbt/mantisbt/security/advisories/GHSA-fh48-f69w-7vmp and covered by the same CVE ID as 0036971 (not yet assigned).

Following feedback from GitHub staff who recommended to treat this as 2 distinct vulnerabilites, a separate Advisory https://github.com/mantisbt/mantisbt/security/advisories/GHSA-73vx-49mv-v8w5 was opened and a new CVE request submitted.

dregad

dregad

2026-03-23 13:02

developer   ~0070904

CVE-2026-33548 assigned.

Related Changesets

MantisBT: master-2.28 f32787c1

2026-03-16 07:39

dregad


Details Diff
Escape unknown tag name in Timeline

Timeline API retrieves data from the bug_history table. It can happen
that the tag name stored there no longer exists (e.g. if it has been
renamed or deleted).

In this case, tag_get_by_name() returns false (obviously), causing
IssueTagTimelineEvent::html() to fall back to displaying the name stored
in the Timeline event as-is, but lack of proper escapeing was allowed
XSS / HTML injection.

Fixes 0036973
Affected Issues
0036973
mod - core/classes/IssueTagTimelineEvent.class.php Diff File