Skip to content

Location privacy bypass: profile updates and DM invitations leak precise geohash #13

Description

@calsbot

Summary

The geohash k-anonymity system only protects the discover query path. Two other paths bypass it entirely, leaking precise user locations to the server.


🔴 Critical

1. Profile update bypasses the entire decoy system

When updateProfile is called, it sends [currentLoc.geohash, ...neighbors(currentLoc.geohash)] — the real cell + its direct neighbors, no decoys. The server stores these verbatim in geohash_cells. The decoy system only protects the query side, not the storage side. The server knows exactly where you are.

2. DM invitations leak precision-7 location (~150m)

chat.ts grabs geohashCells[0] and sends it as senderGeohashCell — no decoys, no truncation. The server stores it raw, and the recipient sees it raw. That's a 150m×150m cell handed over in plaintext.


🟠 High

3. Discover endpoint sorting leaks the real cell

The server scores results by longest shared prefix between query cells and stored profile cells. An attacker querying with an expanding grid can observe which cell gets the highest proximity score — that's the real one.

4. Invitation geohash isn't truncated

The discover endpoint truncates returned geohashes to precision 5 (~5km). The invitation endpoint doesn't. So DMs leak ~40x more precise location than discovery does.


🟡 Medium

5. IP sent to third-party GeoIP service

The /location/ip fallback sends the user's IP to ip-api.com. That's a third party logging users' IPs — undermines the privacy story.

6. Decoys are all geographically clustered

All 11 decoys are neighbors-of-neighbors (~5km radius). Over multiple requests, the real cell is the one that appears in every query. A statistical attack across sessions narrows it down quickly.


Root Cause

There are two location submission paths — discover queries (has decoys) and profile updates (no decoys). The decoy system only covers one of them. The profile update is the one the server actually stores, so the privacy guarantee is effectively bypassed.

Proposed Fixes

  1. Profile update: Store only a truncated geohash (precision 4-5, ~5-40km) instead of the full precision cell + neighbors
  2. DM invitation: Truncate senderGeohashCell to precision 4-5 before sending
  3. Discover sorting: Remove proximity scoring or apply it client-side only
  4. IP fallback: Use Cloudflare headers (cf-ipcity, cf-iplatitude, cf-iplongitude) instead of third-party API — already available through the tunnel
  5. Decoys: Add geographically distant decoy cells (different cities/regions) to defeat statistical correlation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions