Cross-object authorization issue in /testcase-detail/update-issue
Summary
/testcase-detail/update-issue authorizes access to a testcase, but then performs an issue-tracker update on a request-supplied issueId without first binding that issueId to the testcase’s currently linked issue.
As a result, a user who is authorized to access one testcase can use that testcase-scoped authorization to trigger updates on a different issue ID supplied in the request.
Affected file
src/appengine/handlers/testcase_detail/update_issue.py
Affected flow
Handler.post
Handler.update_issue
Technical details
The request accepts:
testcaseId
issueId
needsSummaryUpdate
The access-control decision is made for the testcase referenced by testcaseId.
However, the issue update path then uses the request-supplied issueId to fetch and update an issue through the trusted issue-tracker integration.
The relevant behavior is:
- Access is checked for the testcase.
- The handler accepts
issueId from the request.
- The issue tracker fetches that supplied issue ID.
- The handler updates issue fields and saves the issue.
- The testcase is then rebound by setting
testcase.bug_information to the supplied issue ID.
This means authorization is established for one object type, the testcase, while the state-changing write is performed on another object, the issue selected from request input.
Expected behavior
Before performing the issue-tracker write, the handler should verify that the request-supplied issueId is already authorized in relation to the testcase.
For example, the handler should require that the supplied issue ID matches the testcase’s existing linked issue or another explicitly allowed issue relationship before applying comments, labels, title changes, or rebinding.
Observed behavior
Runtime validation showed the following sequence:
=== BEFORE ===
testcase bug_information: 1111
target issue title: ORIGINAL_TITLE
target issue labels: {'old-label'}
[GET_ISSUE] issue_id=2002
[SAVE] issue_id=2002
[SAVE] title=POC summary for testcase 1001
[SAVE] labels={'clusterfuzz-label', 'old-label'}
[SAVE] new_comment='POC comment from lowpriv@example.com for testcase 1001'
[TESTCASE_PUT] bug_information=2002
[UPDATE_GROUP_BUG] group_id=None
[HTTP_STATUS] 200
[HTTP_BODY] '{"testcaseId": 1001, "bugInformation": "2002", "groupBugInformation": null}'
=== AFTER ===
testcase bug_information: 2002
testcase put called: True
target issue title: POC summary for testcase 1001
target issue labels: {'clusterfuzz-label', 'old-label'}
target issue comments: ['POC comment from lowpriv@example.com for testcase 1001']
This demonstrates that a request using a testcase initially linked to issue 1111 can supply issueId=2002, resulting in an update to issue 2002 and rebinding of the testcase to 2002.
Security impact
This is a cross-object authorization issue in the issue update flow.
A user with testcase-scoped access can cause the trusted issue-tracker integration to perform state-changing updates on an issue selected from request input, including:
- adding a generated comment
- updating the issue title when summary update is enabled
- applying policy-driven labels
- rebinding the testcase to the supplied issue ID
Suggested fix
The handler should enforce an authorization/binding check before performing the issue update.
Possible approaches:
- reject
issueId values that do not match the testcase’s existing bug_information or another valid linked issue relationship
- perform rebinding only after an explicit authorization check for the target issue
- separate “link testcase to existing issue” from “update issue metadata” so that linking does not automatically grant write authority to the supplied issue
- ensure comments, title updates, and labels are applied only after the target issue is verified as authorized for that testcase
poc_http_output.txt
poc_update_issue_http.py
poc_update_issue_runtime.py
Cross-object authorization issue in
/testcase-detail/update-issueSummary
/testcase-detail/update-issueauthorizes access to a testcase, but then performs an issue-tracker update on a request-suppliedissueIdwithout first binding thatissueIdto the testcase’s currently linked issue.As a result, a user who is authorized to access one testcase can use that testcase-scoped authorization to trigger updates on a different issue ID supplied in the request.
Affected file
src/appengine/handlers/testcase_detail/update_issue.pyAffected flow
Handler.postHandler.update_issueTechnical details
The request accepts:
testcaseIdissueIdneedsSummaryUpdateThe access-control decision is made for the testcase referenced by
testcaseId.However, the issue update path then uses the request-supplied
issueIdto fetch and update an issue through the trusted issue-tracker integration.The relevant behavior is:
issueIdfrom the request.testcase.bug_informationto the supplied issue ID.This means authorization is established for one object type, the testcase, while the state-changing write is performed on another object, the issue selected from request input.
Expected behavior
Before performing the issue-tracker write, the handler should verify that the request-supplied
issueIdis already authorized in relation to the testcase.For example, the handler should require that the supplied issue ID matches the testcase’s existing linked issue or another explicitly allowed issue relationship before applying comments, labels, title changes, or rebinding.
Observed behavior
Runtime validation showed the following sequence:
This demonstrates that a request using a testcase initially linked to issue
1111can supplyissueId=2002, resulting in an update to issue2002and rebinding of the testcase to2002.Security impact
This is a cross-object authorization issue in the issue update flow.
A user with testcase-scoped access can cause the trusted issue-tracker integration to perform state-changing updates on an issue selected from request input, including:
Suggested fix
The handler should enforce an authorization/binding check before performing the issue update.
Possible approaches:
issueIdvalues that do not match the testcase’s existingbug_informationor another valid linked issue relationshippoc_http_output.txt
poc_update_issue_http.py
poc_update_issue_runtime.py