[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).

Screenshots of comments:
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

  1. Log in as admin, enable Jira Service Management if it is not enabled

  2. On the left-side panel click Apps -> Approval Path

  3. Go to Settings -> General and enable Allow manual initiation of approvals

  4. Go to Definitions

  5. Click Create

  6. Set any name

  7. Select the JSM project in Space

  8. Click Add step -> and the User step, select the current user in the step settings

  9. Click Save definition

  10. Using Jira UI create a ticket in the JSM project (as a target to get a title of the issue)

  11. Open the created issue

  12. On the right-side panel expand Approval Path

  13. On New tab click Start to start an approval

  14. Go to requests history and find there a request to POST https://app.approval-path.com/connect/jira/create, get the approvalId value from the response

Part 2. The vulnerability

  1. Go to https://<INSTANCE>.atlassian.net/servicedesk in an incognito browser window and sign up

  2. Confirm email to complete sign up

  3. Go to https://<INSTANCE>.atlassian.net/plugins/servlet/ac/ovh.atlassianinc.approval-path.jira/approval-dialog?classifier=json with the collection id from step 16 of part 1 and get the url and the jwt values from the response

  4. Decode as base64 the JWT payload from teh previous step (the part between dots) and get the sub claim from the decoded value - this is the customer id

  5. Send the request below with the url value 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.

Activity

Igor Hercer 25 March 2026, 10:44

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

Kamil Zarychta 23 March 2026, 08:23

Call chain analysis

  1. canNotifyApprover(ctx) — only checks whether the current user has the NOTIFY_APPROVER permission. It does not validate the recipients.

  2. ReminderRequest — contains Set<UserEmail> receivers (any email addresses), id (approval ID), subject, message, etc. There is no field referencing the step.

  3. NotificationService.sendCustomReminder — retrieves the approval path and sets stepId to the active step (getActiveStepId(path)), but uses it only to render action links in the notification. It never validates whether the receivers are approvers on that active step.

  4. JiraNotification.sendCustomReminder — sends the notification to all email addresses from receivers without any verification.

Gap

A user with the NOTIFY_APPROVER permission can send a reminder to any email address provided in receivers, regardless of whether that user is an approver on the active step.

Suggested solution: we should add stepId to ReminderRequest to 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.