Pending

User tests: Successful: Unsuccessful:

avatar kalt2212
kalt2212
1 Oct 2026

Pull Request resolves # .

  • I read the Generative AI policy and my contribution is either not created with the help of AI or is compatible with the policy and GNU/GPL 2 or later.

Summary of Changes

The ajax.fetchUserState task in com_guidedtours persists tour state for the current user: it writes to #__user_profiles (guidedtour.id.<id> -> completed / skipped / delayed) and dispatches the onBeforeTourSaveUserState / onAfterTourSaveUserState plugin events. The component dispatcher deliberately skips the usual access check for this task so every logged-in backend user can record their own tour progress -- but the controller never validated the session CSRF token, accepting plain GET requests with no token at all.

This PR adds a Session::checkToken('get') guard at the start of fetchUserState(), following the same pattern as the other core Ajax controllers (e.g. com_categories fetchAssociations), and sends the token from the guided tours script, which already receives it as the com_guidedtours.token script option. Fail-closed: a missing or wrong token returns an invalid-token JSON error. Only the source file (build/media_source/...) is touched; the compiled asset in media/ is gitignored and built.

The tid / sid parameters are integers and context is whitelisted, so the token check was the only missing piece.

Testing Instructions

  1. Log in to the backend as an administrator and open any page that loads the guided tours script.
  2. In the browser devtools, confirm the ajax.fetchUserState request now carries the session token (&<token>=1 in the URL).
  3. Complete or skip a guided tour and confirm your tour state is still saved correctly.
  4. Replay the request with the token removed: confirm the response is a JSON error with the "Invalid Token" message.

Actual result BEFORE applying this Pull Request

ajax.fetchUserState accepted plain GET requests with no CSRF token: a malicious page could flip any logged-in administrator's tour state (completed / skipped / delayed) via CSRF, and any low-privilege backend user could hit the endpoint directly.

Expected result AFTER applying this Pull Request

Requests without a valid session CSRF token are rejected with an invalid-token JSON error; legitimate requests carrying the token work exactly as before.

Link to documentations

Please select:

  • Documentation link for guide.joomla.org:

  • No documentation changes for guide.joomla.org needed

  • Pull Request link for manual.joomla.org:

  • No documentation changes for manual.joomla.org needed

avatar kalt2212 kalt2212 - open - 1 Oct 2026
avatar kalt2212 kalt2212 - change - 1 Oct 2026
Status New ⇒ Pending
avatar joomla-cms-bot joomla-cms-bot - change - 1 Oct 2026
Category ⇒ Administration JavaScript Repository NPM Change
avatar krishnagandhicode
krishnagandhicode - comment - 1 Oct 2026
avatar krishnagandhicode
krishnagandhicode - comment - 1 Oct 2026

Please use the required/given PR description template : https://github.com/joomla/joomla-cms/blob/5.4-dev/.github/PULL_REQUEST_TEMPLATE.md

avatar kalt2212 kalt2212 - change - 1 Oct 2026
The description was changed
avatar kalt2212 kalt2212 - edited - 1 Oct 2026
avatar kalt2212
kalt2212 - comment - 1 Oct 2026

Done -- PR description updated to follow the template, including the Generative AI policy checkbox and testing instructions.

avatar muhme muhme - test_item - 3 Oct 2026 - Tested successfully
avatar muhme
muhme - comment - 3 Oct 2026

I have tested this item ✅ successfully on afee660

Tested with JBT

  • Seen before PR tour-completed request w/o token
    • GET https://localhost:7154/administrator/index.php?option=com_guidedtours&task=ajax.fetchUserState&format=json&tid=12&sid=6&context=tour.complete
  • Applied PR with Patch Tester and npm run build:js
    • Deleted state:complete database entry in user_profiles table
    • Seen PR tour-completed request w/ token:
      • https://localhost:7154/administrator/index.php?option=com_guidedtours&task=ajax.fetchUserState&format=json&2c3427c84ce0428aa22437c98d808dd1=1&tid=12&sid=6&context=tour.complete
    • Database entry PR "state":"completed"is created
    • Deleted state:complete database entry in user_profiles table
    • Replayed the request w/ token and getting 200 success and DB entry is created
    • Deleted state:complete database entry in user_profiles table
    • Replayed the request with w/o and w/ modified token and getting
      • {"success":false,"message":"The most recent request was denied because it had an invalid security token. Please refresh the page and try again.","messages":null,"data":null}
    • No unusual PHP or Joomla log messages, no JS console messages

This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/48538.
avatar muhme
muhme - comment - 3 Oct 2026

I have tested this item ✅ successfully on afee660

Tested with JBT

  • Seen before PR tour-completed request w/o token
    • GET https://localhost:7154/administrator/index.php?option=com_guidedtours&task=ajax.fetchUserState&format=json&tid=12&sid=6&context=tour.complete
  • Applied PR with Patch Tester and npm run build:js
    • Deleted state:complete database entry in user_profiles table
    • Seen PR tour-completed request w/ token:
      • https://localhost:7154/administrator/index.php?option=com_guidedtours&task=ajax.fetchUserState&format=json&2c3427c84ce0428aa22437c98d808dd1=1&tid=12&sid=6&context=tour.complete
    • Database entry PR "state":"completed"is created
    • Deleted state:complete database entry in user_profiles table
    • Replayed the request w/ token and getting 200 success and DB entry is created
    • Deleted state:complete database entry in user_profiles table
    • Replayed the request with w/o and w/ modified token and getting
      • {"success":false,"message":"The most recent request was denied because it had an invalid security token. Please refresh the page and try again.","messages":null,"data":null}
    • No unusual PHP or Joomla log messages, no JS console messages

This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/48538.

Add a Comment

Login with GitHub to post a comment