# Privacy mURL is a command-line tool that runs on your own computer. It has **no telemetry, no analytics, no crash reporting, no advertising, no accounts and no update checks**, and the project runs no server that the software contacts. The mURL project collects nothing about you. What follows is exactly what does leave your device, when, and to whom. It describes mURL 0.5.2: the `murl` command and, where it is installed, `murl-daemon`. Changes to this page are recorded in the repository history. ## What leaves your device ### Manifest downloads mURL itself uses the network for one thing: downloading the manifest that says what a remote mURL contains. **When.** When you use a remote address (anything other than `murl://local/…`) with a command that needs its manifest: `resolve`, `open` (including `--dry-run`, and links you click after `murl os install`), `validate`, `inspect`, `verify` or `export`. A running `murl-daemon` downloads the same way when `murl open` hands it an address, or when another program running as you asks it to. If a fresh copy is already in the local cache, nothing is downloaded, unless you pass `--refresh`. `resolve`, `open` and `export` also download every remote mURL nested inside a manifest, each from its own host, and that includes mURLs nested in a manifest stored on your computer. By default one resolution reads at most 8 manifests, the address you gave included. These downloads happen **before** mURL shows you what a destination contains and asks for your consent. That is how it finds out what to show you. `--offline` makes no request at all. **Where to.** Only to the host named in each address: `murl://example.com/team/onboarding` is fetched from `https://example.com/.well-known/murl/team/onboarding.murl.json`. A nested mURL can name any other host on the network. Whoever runs that server, not the mURL project, receives the request and decides what to do with it. A manifest downloaded from the network cannot nest an address on your own computer: not `localhost`, `127.0.0.1` or `*.localhost`, and not `murl://local/…`. mURL refuses such a manifest before looking anything up, so it neither sends a request to a port on your computer nor tells that server which local names you have. A manifest served from `localhost` may nest `localhost` addresses but not `murl://local/…` names. **What is sent.** A lookup of the host name through your system's resolver (for a name such as `printer` or `printer.local`, your system may ask your local network), then this HTTPS request: ```http GET /.well-known/murl/team/onboarding.murl.json HTTP/1.1 Host: example.com User-Agent: murl/0.5.2 Accept: application/murl+json, application/json ``` There are no cookies, no identifiers and no request body, and the request carries nothing about your files or other resources. The `?query` and `#selector` parts of the address are not sent. Like any web request, it shows that server your IP address, the time, the address you asked for and your mURL version. The host name also travels in the TLS handshake (SNI) and in the lookup. While mURL is running it may resume a TLS session with a server it already contacted, as browsers do, which lets that server link those requests; `murl-daemon` keeps running until you stop it. **Safeguards.** * HTTPS only. Plain http is used just for `localhost`, `127.0.0.1` and `*.localhost`, and those requests can only reach your own computer. * A host is refused when every address it resolves to is private, link-local or loopback; otherwise only its public addresses are used. Devices with public addresses are not covered by this check, which with IPv6 can include machines on your own network. * Redirects are not followed, unless you turn them on with `limits.maxRedirects` in `config.json`. A redirect can then lead to another host, but an https request is never redirected to http. * System proxy settings and proxy environment variables are not used. * Certificates are checked against a built-in set of root certificates, with no revocation lookups, so no other server is contacted. ### What mURL hands to other programs When you approve a resource, mURL passes its target to a program on your computer. That program may then use the network on its own terms: * web addresses, `mailto:` and `geo:` links, files and folders go to your default handler: `explorer.exe` on Windows, `xdg-open` on Linux, `open` on macOS, which hand each one to the app your system has set for it (browser, mail client, maps, file manager, or the app for that type of file); * terminals, SSH, remote-desktop and `custom:` targets go only to a program you registered with `murl handler`. mURL sends nothing about these resources itself. The one exception: after you approve a file, folder or terminal, mURL checks that the path exists, and on a network drive or a mounted share that check reaches the share's server. A manifest may not point a file, folder, terminal or `custom:` target at a network path such as `\\server\share` or `//server/share`: no such target may start with two slashes or backslashes. Paths inside shares you connected yourself are still allowed, such as a mapped drive on Windows, or on Linux and macOS a mounted share or an automounter path like `/net/…`. On Windows, mURL gives `explorer.exe` each target as a single quoted argument, so text inside a web address cannot make Explorer open a network share instead. ### Clickable links On Windows and Linux, `murl os install` makes `murl://` links clickable for your user account. On Windows it writes `HKCU\Software\Classes\murl`; on Linux, a desktop entry in `~/.local/share/applications` (or `$XDG_DATA_HOME/applications`), which it sets as the default for `murl://` links with `xdg-mime`. On macOS it registers nothing; links there need the app bundle built from the source tree. Clicking a link runs `murl open-url`, which downloads manifests as described above before it shows the consent prompt. `murl os uninstall` deletes the registry key or the desktop entry; on Linux, the `xdg-mime` default it set stays behind but points at nothing. The winget, Scoop and Homebrew packages never register links themselves. ## What stays on your device | What | Windows | Linux | macOS | |---|---|---|---| | Your settings, handlers, pinned public keys and signing keys | `%APPDATA%\murl\` | `~/.config/murl/` | `~/Library/Application Support/murl/` | | Names you install with `murl name` or `murl import` | `%LOCALAPPDATA%\murl\data\names\` | `~/.local/share/murl/names/` | `~/Library/Application Support/murl/data/names/` | | Copies of downloaded manifests, each with the address it came from and when | `%LOCALAPPDATA%\murl\cache\` | `~/.cache/murl/` | `~/Library/Caches/murl/` | `MURL_CONFIG_DIR`, `MURL_DATA_DIR` and `MURL_CACHE_DIR` override these locations, and on Linux so do the `XDG_*` variables. `murl keygen --out` saves a key wherever you choose instead. `murl-daemon`, which is not part of the Windows release, uses the Linux locations on macOS as well and talks to `murl` over a Unix socket that only your account can open. mURL uploads none of this. On Windows, `%APPDATA%` is the roaming folder: if your organization uses roaming profiles, Windows itself copies it, signing keys included, to its servers. Signing keys from `murl keygen` are stored unencrypted, so protect them as you would an SSH key. Diagnostics are printed to the terminal; mURL writes no log file. Under the systemd user service, `murl-daemon`'s output goes to your user journal, and that output includes the address of every manifest it downloads. To remove everything: * `murl cache clear` empties the cache. On macOS it does not touch `murl-daemon`'s own cache in `~/.cache/murl/`. * If you registered links, run `murl os uninstall` before uninstalling the package, which leaves the registration behind. * If you used `murl-daemon`, stop it and run `murl-daemon service uninstall`. * Then delete the `murl` folders above (on macOS, also `~/.config/murl/`, `~/.local/share/murl/` and `~/.cache/murl/` if you used `murl-daemon`) and any key you saved elsewhere with `murl keygen --out`. ## The website is a static site hosted on GitHub Pages. It has no analytics and no cookies, and it loads nothing from other sites: the script libraries and fonts it uses are copies served from the site itself. Your browser's local storage keeps your theme choice and which tab each set of tabs last showed. The playground runs entirely in your browser and sends nothing you type into it anywhere. GitHub, as the host, processes request data under the [GitHub Privacy Statement](https://docs.github.com/site-policy/privacy-policies/github-general-privacy-statement). ## Contact Questions about this page: . Security problems: see [SECURITY.md](SECURITY.md).