Skip to content

v0.3.3 — security: geolocation trust boundary

Choose a tag to compare

@mrCode mrCode released this 31 Aug 15:56
· 37 commits to master since this release

Security release — a full-codebase scan of the geolocation trust boundary.

The geolocation HTTP response is a trust root: it is written into config.toml, replayed on every run, printed to terminals, and painted on the bar. It was being handled as if it were our own data. Three findings:

1. Cleartext transport (high). The endpoint was http://ip-api.com/json/, and auto-relocate fires on every NetworkManager connection-up — so anyone on-path on a hostile network could permanently rewrite your coordinates, and with them your prayer times. The existing timezone cross-check did not close this: it only catches cross-country spoofing and is skipped entirely when timezone detection returns nil.

The provider is now https://ipwho.is/ (ip-api's free tier is HTTP-only), and a guard refuses any non-HTTPS endpoint except loopback, so a pinned URL cannot silently downgrade. Coordinates must be numeric and in range; the country code must be two letters.

2. Terminal control-character injection (high). An attacker never sends a raw ESC byte — that would break TOML parsing. They send the six-character escape sequence that a TOML parser decodes into one (backslash, then u001b). It carries no markup, survives naive filtering, and forms a valid TOML basic string — which the parser then decodes back into a real ESC on load. The payload is OSC 52, which writes your clipboard; Omarchy's shipped Alacritty config sets osc52 = "CopyPaste", so the next paste into a shell would run attacker-chosen text.

Sanitisation now strips C0/C1 controls and Unicode format characters (covering bidi overrides), applied at every display sink — the status JSON, the TUI, the plain status line, the notification body, and the auto-relocate log line.

3. TOML injection (low/medium). city/country were spliced into config.toml unescaped, so a quote closed the literal early and the rest parsed as TOML — enough to flip auto_update back on for someone who had pinned their location. Escalation to code execution via [audio].player was not reachable, since the parser rejects duplicate table headers.

Sanitisation is applied at every sink rather than at ingress alone, because poisoned values may already be on disk from before this release.