Skip to content

Security: bjarneo/flux

Security

docs/security.md

Security

Documentation index

This page tells what a paired device can do on the computer and what the network exposes. It also tells which setting turns a feature off, when one exists. A paired device is an Android phone, an iPhone, or a Mac that you paired with fluxd.

Global settings in ~/.config/flux/config.toml apply to every paired device. The per-device access settings can restrict a feature for one device. A device restriction cannot enable a feature that the global settings disable. To remove all access for one device, unpair it.

Pair only with your own device

The pairing key has 16 uppercase hex digits in 4 groups of 4, for example 5EE6 825F 974E D59A. Both devices compute it from their 2 certificates and the time of the request. The key has 64 bits. So a device between the phone and the computer cannot find a certificate with the same key while the request is open.

Before you accept a pair request, check these items:

  • You started the pairing yourself, now.
  • The request names your device.
  • All 16 characters are the same on both screens.

If 1 item is not true, reject the request. An earlier Flux app shows only 8 characters. Update Flux on the computer and on each phone, iPhone, and Mac before you pair, and compare all 16 characters.

A pairing that the computer starts needs a confirmation on the computer too. After the device accepts, the Flux window, the notification, and flux-cli pair ask you to confirm the key. fluxd pins the device only after that step. So a device that copies the name of your phone cannot pair when you select it by mistake. Each accept and confirm names the key that you compared, and fluxd refuses it when the open pairing has another key. Without a key, flux-cli accept shows the key of the open pairing and asks you to compare it before it sends the key. When stdin is not a terminal, it accepts nothing and prints the command with the key. The Flux window and the notification also send the key with a reject. Without a key, flux-cli reject rejects the pairing that is open when it runs.

After the pairing, fluxd pins the certificate of the device. It refuses each link that does not show that certificate. Each device in flux-cli status --json has a fingerprint: 16 hex digits from the public key of its certificate. flux-cli status shows the device ID and the fingerprint under each device. The device card on the page of the device in the Flux window shows the fingerprint under Certificate. flux-cli pair and flux-cli accept print the device ID and the key. flux-cli unpair prints the device ID and the fingerprint. See pairing security and pairing and trust.

What a paired device can do

The table lists what a paired device can do on the computer with the default settings. It also tells which setting turns a feature off, when one exists.

Feature Default What a paired device can do Turn it off
Files On Send files into download_dir, scans into scan_dir, and photos, screenshots, and signatures into photo_dir. fluxd also puts a signature on the clipboard. fluxd makes each name safe and never replaces a file. See files, clipboard, and links. No setting. Unpair the device.
Links and text On Open an http or https URL with a host in the browser. Each other value goes on the clipboard as text. No setting. Unpair the device.
Clipboard sync auto_clipboard = true Get each text and image that you copy on the computer, and put text and images on the clipboard of the computer. auto_clipboard = false
Browse PC share_home = true Read the home folder, download_dir, and ~/Documents, ~/Pictures, ~/Music, and ~/Videos. fluxd hides each name that starts with a dot, such as ~/.ssh, and the Flux folders. The search of file names uses the same rules. The device cannot change a file. See Browse PC. share_home = false. It ends each session at once.
Notifications notifications = true Show its notifications on the computer. notifications = false
Do Not Disturb sync_dnd = true Turn Do Not Disturb of the computer on and off. sync_dnd = false
Calls pause_media_on_call = true Pause the media players of the computer during a call. pause_media_on_call = false
Media On Play, pause, skip, seek, and set the volume of the media players of the computer. No setting. Unpair the device.
Desktop commands No commands Run each command in commands. flux-cli commands remove ID
herdr agents herdr = true Read the list of the herdr agents and the recent output of each agent. Watch the live terminal of an agent pane, with no input. herdr = false
Agent control herdr_control = false Send keys and prompts to the agents, start agents, and close them. Control the live terminal of an agent pane: type, paste text and images, click at any cell, scroll, and resize the pane. An image paste replaces the clipboard of the computer, also with auto_clipboard = false. A click can press each button of the agent, for example an approval. An agent runs commands, so the device can run any command as your user. herdr_control = false
Terminals herdr_terminals = false Read and type in each herdr pane that has no agent, also a sudo -i shell or an SSH session that you opened. Watch and control the live terminal of such a pane. Needs herdr_control. herdr_terminals = false
Remote input remote_input = false Move the pointer and type in each window, also on the lock screen. See touchpad and keyboard. flux-cli input off
Remote desktop remote_desktop = false See the screen, each window, and the lock screen. See remote desktop. flux-cli desktop off. It stops each stream at once.
Webcam, microphone, and screen mirror On Stream its camera to the Flux Camera device, its microphone to a PipeWire source, and its screen to a window. The device starts each stream. The computer can ask the device to start its camera or its microphone, but the device asks its user first. See camera and streams. No setting. flux-cli webcam stop, flux-cli mic stop, and flux-cli screen stop stop a stream.
Approvals Off Approve sudo, and hyprlock or polkit-1 when you enable them, for the user who enrolled the device. See fingerprint approval. sudo flux-cli approve disable or sudo flux-cli approve remove

To change a setting, edit ~/.config/flux/config.toml, then reload fluxd:

systemctl --user reload fluxd

The Access card of the Flux window turns remote input and the remote desktop on and off for every device, with Turn on and Turn off. A script can call the IPC method settings.set. See IPC. See configuration for each setting.

The apps ask for the screen lock, Face ID, or Touch ID before the touchpad, the remote desktop, agent replies, and the live terminal. This check protects the app only, and fluxd cannot see it. The settings in config.toml are the checks that fluxd makes. So turn on remote_input, remote_desktop, herdr_control, and herdr_terminals only when you trust each paired device.

What a device sends to the computer

Flux for Android has 6 switches that share data of the device with the computers. They are on the Sync screen in Computers:

  • Text messages lets each paired computer read your conversations and send text messages.
  • Share notifications sends the notifications of other apps, each with the icon of its app as a PNG of 96 × 96 pixels. fluxd accepts an icon of at most 256 × 256 pixels, decodes it, and encodes it again before the notification server reads it. A notification whose visibility, or whose channel lock screen visibility, is VISIBILITY_SECRET stays on the phone. The lock screen setting of the whole phone does not change what Flux sends. A button that needs the phone unlock also stays on the phone.
  • Send new screenshots and Send new photos send new images of the camera app and the screenshot tool.
  • Sync clipboard sends the text and the images that you copy while Flux is on the screen. A 1-tap path sends a copy from another app. See send a copy from another app.
  • Call alerts sends the state of calls, and with more permissions the number and the name of the caller.

Each switch applies to every paired computer, not only to the computer whose page shows it. See sync switches. Flux for iOS and Flux for macOS send less, because their systems give apps less access. See Flux for iOS and Flux for macOS.

The computer can send files, links, text, and notifications to a paired device. Each app opens a link or a file from the computer only after a tap. Flux for Android installs no app that the computer sends, except a newer Flux with the signing key of the installed Flux, after your tap.

The computer can ask a paired device to start its camera or its microphone. flux-cli webcam start, flux-cli mic start, and Start in the Flux window send the request. The device never turns on its camera or its microphone without a tap on the device, also while Flux is on its screen. The tap is the consent. fluxd sends at most 1 request of each kind to a device in 3 seconds, and the device ignores a request that comes sooner. See start from the computer.

Network ports

fluxd listens on these ports on all network interfaces:

Port Use
The first free TCP port from 12100 to 12108 Links from devices
UDP 12100 Identity broadcasts from devices

flux-cli status shows the TCP port in its first line. fluxd also publishes the _flux._udp service through Avahi, and it sends its identity to UDP port 12100 of the local networks. For a device without flux.tunnel, fluxd listens for a payload on a TCP port from 12070 to 12099 on the local address of the link. Flux and KDE Connect use different ports, so both can run on the same computer at the same time.

fluxd opens the links to the devices itself, so Flux needs no inbound firewall rule. The default Omarchy firewall blocks inbound traffic to the Flux ports, and it lets mDNS in. With this firewall, fluxd finds the devices through mDNS and the extra addresses. The UDP broadcasts of the devices reach fluxd only without such a firewall. To see the rules, run:

sudo ufw status verbose

Without such a firewall, each host that reaches the computer can open a link to fluxd and send a pair request. The same is true for a rule that lets in the traffic of an interface, for example ufw allow in on tailscale0. The limits below apply to such hosts.

The Android phone, the iPhone, and the Mac also listen on TCP ports 12100 to 12108 for links. They listen on TCP ports 12070 to 12099 for payloads, tunnels, and streams. Flux for Android takes a link from a computer that is not paired only while Flux is on the screen or while it scans.

Album art

Besides the paired computers, the apps connect to 1 other kind of host. The Media screen loads the album art from the https address that a player on the computer reports. That host is usually a server of the music or video service, and it sees the IP address of the device. fluxd sends only https addresses to the devices, never a file: address with a local path. Without an address, the screen shows no art and loads nothing.

Devices that are not paired

Any host on the network can send an identity and open a link. fluxd ignores each packet of a device that is not paired, except a pair request. It keeps these limits for such devices:

  • A link reads lines of at most 64 KiB.
  • fluxd keeps at most 8 such links, and 2 for each address. A new link closes the oldest one.
  • A link without a pair request closes after 2 minutes.
  • fluxd takes 1 pair request for each device in 2 seconds, shows 1 notification for each device, and keeps at most 4 open requests. At most 2 of them come from 1 address.
  • When a request of a device ends with a withdraw, a reject, a timeout, or the end of its connection, fluxd refuses a new request of that device for 30 seconds.
  • When fluxd refuses a request because too many requests are open, the Flux window shows the name and the address of the device.
  • Dials to these devices share a limit of 16 at the same time. Dials to paired devices do not count, so these devices cannot keep a paired device offline.

See limits for devices that are not paired for the complete list.

Unpair a device

To unpair a device from the computer, run:

flux-cli unpair "Pixel 8"

A name matches only a device that is paired or connected, and a paired device comes first. When the name still matches more than 1 device, the command returns the ambiguous error with the device IDs. See pair and discover for the match rule of each command. Give the device ID in place of the name.

An unpair from either side ends every session of the device:

  • fluxd sends the unpair message, pair: false, to the device and closes the link.
  • Browse PC, the streams, the remote desktop, and remote input stop. fluxd drops the input that waits and releases a held button.
  • fluxd sends no answer of a herdr read, a reply, or a start that still runs.
  • fluxd removes the notifications, the messages, the battery state, and the extra addresses of the device. It closes the desktop notifications of the device, because their buttons no longer reach it.

When fluxd cannot save devices.json, the command returns the not_saved error. The device is then unpaired only until fluxd restarts, because ~/.local/share/flux/devices.json still has it. Fix the cause in the error, for example the permissions of the file. Then restart fluxd and unpair the device again:

systemctl --user restart fluxd
flux-cli unpair "Pixel 8"

After an unpair, the device must send a new pair request, and you must accept it again.

If you lose a device, unpair it on the computer at once. If the device can approve sudo, also remove its key:

sudo flux-cli approve remove

An unpair on the Android phone, the Mac, or the iPhone deletes its approval key for that computer. The key file on the computer stays until you run sudo flux-cli approve remove.

There aren't any published security advisories