[Bugcrowd] JSM customers can get title of any issue containing any approval on the instance
Description
Note #1:
This submission has been created by researcher on 07.02.2026 and triaged by Bugcrowd team on 10.03.2026. Since then we migrated most modules to Forge.
QA team could not reproduce the issue, however we should double check if the vulnerability still occurs after the migration.
Note #2:
The steps provided by researcher are pasted below, however, there has been additional discussion between Bugcrowd staff and the researcher, please see the below screenshots (in the expand item).
curl -i -s -k -X $'POST' \-H $'Cookie: <COOKIE>' \$'https://<INSTANCE>.atlassian.net/plugins/servlet/ac/ovh.atlassianinc.approval-path.jira/approval-dialog?classifier=json'
Submission details:
I found that JSM customers can send notification about any approval on the instance. The email that is received contains links to approve and to reject the approval with access tokens. But I cannot say if it is possible to approve/reject the approval because on my instance the links do not work even when I send a notification to a valid user using the UI without any changes in requests. The access tokens are identical, the only difference in them is the user id. Also, the email contains title of the issue that contains the approval.
Steps to reproduce:
Part 1. Configuration
-
Log in as admin, enable Jira Service Management if it is not enabled
-
On the left-side panel click
Apps->Approval Path -
Go to
Settings->Generaland enableAllow manual initiation of approvals -
Go to
Definitions -
Click
Create -
Set any name
-
Select the JSM project in
Space -
Click
Add step-> and theUserstep, select the current user in the step settings -
Click
Save definition -
Using Jira UI create a ticket in the JSM project (as a target to get a title of the issue)
-
Open the created issue
-
On the right-side panel expand
Approval Path -
On
Newtab clickStartto start an approval -
Go to requests history and find there a request to POST
https://app.approval-path.com/connect/jira/create, get theapprovalIdvalue from the response
Part 2. The vulnerability
-
Go to
https://<INSTANCE>.atlassian.net/servicedeskin an incognito browser window and sign up -
Confirm email to complete sign up
-
Go to
https://<INSTANCE>.atlassian.net/plugins/servlet/ac/ovh.atlassianinc.approval-path.jira/approval-dialog?classifier=jsonwith the collection id from step 16 of part 1 and get theurland thejwtvalues from the response -
Decode as base64 the JWT payload from teh previous step (the part between dots) and get the
subclaim from the decoded value - this is the customer id -
Send the request below with the
urlvalue from the response in step 3:
POST /connect/JIRA/api/atlassian-connect-app HTTP/2Host: app.approval-path.comContent-Type: application/jsonContent-Length: 1236{"url":"<URL>"}
Get the token value from the response. Send the request below with the JWT token, the customer id and the id of the approval:
POST /connect/jira/notification?jwt=<TOKEN> HTTP/2Host: app.approval-path.comContent-Type: application/jsonContent-Length: 1123{"receivers":[{"accountId":"<CUSTOMER_ID>","email":"doesnotmatter@attacker-approval-path.com"}],"from":"attacker <no-reply@app.approval-path.com>","subject":"1337","textMessage":"1337","id":"<APPROVAL_ID>","type":"CUSTOM_REMINDER"}
Check that the customer's email inbox, there will be email. In the email in the bottom you will see the Jira issue ticket that contains the approval. Also, there will be buttons to approve and reject. I tried to send a valid notification and the buttons do not work on my instance. So, I cannot say if they will work for the attacker. It looks like the feature is broken at all.
For testers.
Feel free to contact me if you won’t be able to reproduce the behaviour.
Changed things:
Filters custom reminder receivers to only those who are actually awaiting approvers on the active step — prevents sending notifications to arbitrary accounts/emails
Endpoints that should be secured:
ApprovalRestController (/forge/jira, /forge/confluence):
DELETE /delete/{id}
GET /get-users-for-notification/{id}
PATCH /archive/{id}
PATCH /validity-expiration/{id}
ExportController:
GET /export
DelegateRestController (/forge/jira/rest/delegates, /forge/confluence/rest/delegates):
GET / — getDelegates
GET /{id} — getDelegate
POST / — createDelegate
PUT /{id} — updateDelegate
PATCH /{id}/archive — archiveDelegate
GET /{id}/configs — getDelegateConfigs
WorkflowController (/forge/jira/workflow):
GET /definitions
NotificationController:
POST /notification
GET /custom-reminder-template
Call chain analysis
canNotifyApprover(ctx) — only checks whether the current user has the
NOTIFY_APPROVERpermission. It does not validate the recipients.ReminderRequest — contains
Set<UserEmail> receivers(any email addresses),id(approval ID),subject,message, etc. There is no field referencing the step.NotificationService.sendCustomReminder — retrieves the approval path and sets
stepIdto the active step (getActiveStepId(path)), but uses it only to render action links in the notification. It never validates whether thereceiversare approvers on that active step.JiraNotification.sendCustomReminder — sends the notification to all email addresses from
receiverswithout any verification.Gap
A user with the
NOTIFY_APPROVERpermission can send a reminder to any email address provided inreceivers, regardless of whether that user is an approver on the active step.Suggested solution: we should add
stepIdtoReminderRequestto indicate which step the notification is being sent for. In addition, there should be a validation that the recipients actually belong to that active step and have not voted yet. It should work for all types of steps: User/Group/Email. We should also verify permissions for JSM customers — we should not allow access to approvals that were not started in the JSM space. This will eliminate the gap that currently allows sending a notification to any user.