github dedicatedcode/reitti v5.8.0

4 hours ago

Reitti v5.8.0 Release Notes

Hey everyone, Daniel here! 👋

This release has a new statistics page, and it has three security fixes. I would like to talk about the statistics page first, but that would be doing it in the wrong order, so let's get the serious part out of the way.

Security: Three Advisories, All Fixed

Before anything else: thank you to everyone who reports this kind of thing. reitti is written by one person in their spare time, and its security depends on people who actually read the code and tell me what they find. Every report makes reitti more secure for all of us. Please keep them coming, through the private advisory form on GitHub rather than the issue tracker, so users have a chance to update before the details are public.

All three issues affect v5.7.0 and earlier, are fixed in 5.8.0, and are published here: github.com/dedicatedcode/reitti/security/advisories

1. Memories: share link scope bypass and cross-user photo read

After the last release I already fixed a couple of endpoints that allowed loading data of other users. This time memory blocks were the target when logged in via a magic link. The check verified that a memory belongs to the account behind the token, but not that the token was actually granted for that memory, and the photo endpoint did not check ownership at all. The result: an edit share link for one memory could read, write and delete blocks in every other memory of the same owner, and any authenticated user could read photos in other users' memories. Photos carry capture time and geolocation, which says a lot about where someone lives and how they move, so this one is not cosmetic.

Both paths now go through the same access check as the memory page itself, and magic-link sessions are validated against the resource they were granted for.
Details: GHSA-hqfj-4w5j-45g6

2. Memory image upload: stored XSS through the file extension

There was no validation of which files could be uploaded as memory images. The extension was taken from the client-supplied filename, the content type was guessed from that extension when serving the file, and the result was returned inline. Upload something called evil.html, send the URL to another logged-in user, and the script inside runs in reitti's origin with their session. It needs a victim who clicks the link, which is why this is not critical, but if you do not fully trust the other users on your instance, that is a real risk.

Uploads are now checked for being actual images, and files from users are no longer served in a way that lets a browser execute them.
Details: GHSA-8ch3-46gh-f6g4

3. Shared map styles: privileges and stored XSS

And then the one I would have liked to not write about. reitti lets users create custom map styles, and a style can be marked as shared. That flag was read straight from the request without checking the caller's role, so any normal user could share a style. Style names are written into the page for every user who loads it, and a name containing the right characters closes that block and executes script. Together that means an ordinary user could plant script that runs for everyone else, administrators included, with everything that implies: creating a new admin account, deleting users, resetting passwords, reading private memories.

I am not going to soften this one. GitHub scores it Critical, and that score is fair. It needs an account on your instance, so a single-user instance where you are the only account holder was never really exposed, but on instances where accounts are handed out, this was dangerous.

Only admins can create shared map styles now. That closes the chain at its entry point, and you still have to trust your admin — which I will take as a given fact.

The New Statistics Page

Now to the part I actually enjoyed building.

The statistics page used to be a handful of charts. It is now a full report on your data, and it is the reason this release exists. There is a bar chart icon in the main menu that leads to it, and the documentation has a page per section, so I will keep this short.

You can look at a month, a year or your whole history. The arrows jump to the previous or next period that actually contains data, and clicking the period name opens a picker with every year and month you have.

image

What is in the report, roughly:

  • A headline sentence about the most striking pattern of the period, plus how many days were tracked and how many did not have enough data to be trusted. That second number matters more than you would think.
  • Key figures: distance, the share of weekday time spent at home, places visited and how many were new, your Eddington number, and nights away from home.
  • Weekdays and weekends, side by side: time at home and elsewhere, the distance of a typical day, your top transport mode, when you usually leave and come back, outings and stops.
  • What actually moved you: distance, time and trips per transport mode, with the average speed of each one.
  • Where the days went: every day is classified as Commute, Wander, Travel, Home or Untracked, laid out as a calendar. Days with thin data are faded instead of being quietly counted as normal days.
  • The usual trip, plus a radar that places every visited place by direction and distance around your home. Mine looks exactly like I expected, which is slightly depressing.
  • Routines: places you return to regularly, how often, at what time, for how long.
  • Nights and places, Exploration (only with spatial coverage enabled), comparison with another period, and an Odds and ends section that reminds you of nights away which never became a memory.

Every section has a ? icon explaining what it shows and how to read the numbers, place names link to the place so you can fix a wrong name on the spot, and days link to the timeline of that day.

The Aggregated Timeline Got a New Look

While building the statistics page I had a set of components that answer "what happened in this period" much better than a list does, so I reused them where the list was already failing: when you select more than two weeks, the aggregated timeline now uses them. A month or a year reads as a report about your movement instead of four hundred entries you scroll past.

image

Bug Fixes

  • Duplicated context path in URLs. In the last release I refactored how the base server URL is calculated, and I missed that the context path is now part of the base path. In some places it was then added twice, which produced broken URLs. If you run reitti under a subpath, this is your fix.

Other Changes

  • Fresh translations from Hosted Weblate. Thanks again to everyone translating — it is what keeps reitti usable for people who do not read English comfortably, and I would never get there on my own.

Thank You

  • Everyone who reported the issues above through the advisory form. Three advisories in one release is not a nice scoreboard, but it is three holes closed, and that only happens because someone took the time to write it up properly.
  • All translators for keeping the translations moving release after release.

Help Spread the Word

Word of mouth is what keeps reitti growing. If you know someone looking for a private Google Timeline alternative, a way to geotag their Immich library, or an open Street View to contribute to, mention reitti. I would much rather spend my time writing code than posting on social media, so every mention helps more than you know.

If you want to support the project financially, there are now two ways to do it:

Patreon
Ko-fi


Full Changelog: v5.7.0...v5.8.0

Getting Started

The latest docker-compose.yml is available in the GitHub release assets. Pull the new image, restart, done. There is nothing to configure and no migration to run.

If you have any questions, feel free to add them to the release discussion.

Thank you all for being part of this journey. Happy tracking!

— Daniel

Don't miss a new reitti release

NewReleases is sending notifications on new releases.