Skip to content

Apply the GET read-only rule for session tokens to nested API.getBulkRequest calls #25590

Open

Description

@kasparovabi

Summary

Matomo accepts a session token_auth over GET (with force_api_session=1) only for methods that look read-only. The check in core/Access.php tests the root method name for .get, so API.getBulkRequest passes it, and the nested requests in urls[] then run in the same session context. A write method that is refused when called directly over GET with a session token goes through when it is wrapped in a GET bulk request.

This came up in a HackerOne report (#4142296). The Matomo team closed it as informative because the GET restriction is meant to prevent accidental state changes from URL parameters, not to act as a security boundary, and suggested opening an issue here for the hardening. So this issue is only about making the bulk path follow the same rule as a direct call.

Example, on 5.x (the .get test is still at core/Access.php line 176 on 5.x-dev):

# refused, as intended
GET /index.php?module=API&method=UsersManager.setUserAccess&...&token_auth=<session token>&force_api_session=1

# accepted
GET /index.php?module=API&method=API.getBulkRequest&format=json&token_auth=<session token>&force_api_session=1&urls[0]=method%3DUsersManager.setUserAccess%26...

Possible change, smallest first:

  1. Leave API.getBulkRequest out of the GET exception in core/Access.php. The UI already sends bulk requests with POST.
  2. Or, in API::getBulkRequest(), apply the same read-only rule to each nested method when the token is a session token that did not arrive securely. That would also cover any future dispatcher whose name starts with get.

A regression test can send a GET bulk request with a session token and a nested write method and expect the same error as the direct call.

Your Environment

  • Matomo Version: 5.14.2 (also checked against 5.x-dev)
  • PHP Version: 8.x (official matomo:5-apache image)
  • Server Operating System: Linux (Docker)
  • Additionally installed plugins: none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions