Debian's sensible-browser hands a URL to whatever browser fits the session, but a careless BROWSER value can run a shell command you did not intend. The examples describe the installed sensible-utils version 0.0.22 and do not require a graphical session.
sensible-utils package.sudo: this command selects a browser for a process and does not install software, edit system configuration or open a privileged browser.Start by checking which executable your shell will run and recording the package version. These are read-only checks:
$ command -v sensible-browser
/usr/bin/sensible-browser
$ dpkg-query -W -f='${Package} ${Version}\n' sensible-utils
sensible-utils 0.0.22
The command has a deliberately small interface. Its documented form is sensible-browser url. It does not have a browser-selection option or a configuration file argument.
Checkpoint: if command -v prints nothing, stop here and install sensible-utils through your normal package-management process. Do not copy a script into /usr/local/bin just to make the command appear to work.
sensible-browser first looks at the BROWSER environment variable. If it is set, its value is treated as a shell command string and the URL is supplied as an argument. This is the same general convention described for EDITOR in environ(7).
If BROWSER is unset, or its command returns the shell's command-not-found statuses 126 or 127, the installed script tries desktop and text-browser fallbacks:
/usr/bin/x-www-browser./usr/bin/www-browser.An apparently harmless value in BROWSER can execute a shell command. Do not set it from untrusted text, and do not paste a URL containing shell syntax into a hand-built command string. Keep the browser command fixed and pass the URL as the final argument.
Use a temporary BROWSER value that prints its argument instead of launching a graphical program. This changes only the environment of this one command:
$ BROWSER='printf "selected=%s\n" "$1"' sensible-browser 'https://example.invalid/docs'
selected=https://example.invalid/docs
The exact output should contain the URL you supplied. The example.invalid name is reserved for examples and should not resolve to a real site. This test confirms the argument hand-off without opening a tab or sending a request to a web server.
Checkpoint: verify the temporary setting did not persist:
$ printf 'BROWSER=%s\n' "${BROWSER-unset}"
BROWSER=unset
An assignment placed before one command affects that command only. An assignment such as export BROWSER=... lasts for the rest of the shell session and can surprise scripts started from that shell, so avoid exporting it while testing.
Once the hand-off is clear, point BROWSER at a browser command that is actually installed. command -v is a safe way to check the name before invoking it:
$ command -v xdg-open
/usr/bin/xdg-open
$ BROWSER=xdg-open sensible-browser 'https://example.com/'
This delegates the URL to xdg-open, which then uses the desktop's normal URL handler. The final command may open a browser window, so run it only with a URL you intended to visit. A successful return means the selected command accepted the request; it does not prove that a page loaded or that the URL was safe.
If your preferred browser is a command with its own name, use that name only after checking it:
$ command -v firefox
/usr/bin/firefox
$ BROWSER=firefox sensible-browser 'https://example.com/'
Use the full path when you need to remove ambiguity between multiple installations. If the command needs fixed options, the variable can contain a command string, but quote it carefully and keep the URL supplied by sensible-browser as the argument. Test such a value with the printing example before opening a real page.
First check whether BROWSER is set and whether its command exists:
$ printf 'BROWSER=%s\n' "${BROWSER-unset}"
$ command -v xdg-open
$ command -v firefox
An empty command -v result means that name is not available through your current PATH. It is not a reason to add sudo. Correct the command name, install the intended browser through your normal system process, or unset BROWSER to let the Debian fallbacks decide:
$ unset BROWSER
$ sensible-browser 'https://example.com/'
Recovery: unset is the fix for a bad session-level choice. If you put the setting in a shell startup file, remove or correct that line there and start a new shell. If it is supplied by a service, wrapper or desktop session, change the setting at that source instead; do not edit /usr/bin/sensible-browser.
There is no need to diagnose a missing browser by repeatedly opening URLs. Use the non-opening printf test first, then check the selected executable. A failure from the browser itself can be unrelated to sensible-browser, for example a missing display or a desktop session that is not ready.
For a script, decide whether browser selection is part of the script's contract. If it is, set a known command in the environment and preserve the URL as one shell argument:
url='https://example.com/help'
BROWSER=xdg-open sensible-browser "$url"
status=$?
if [ "$status" -ne 0 ]; then
printf 'browser selection failed with status %s\n' "$status" >&2
exit "$status"
fi
Do not use eval to assemble the command. Do not interpolate an untrusted value into BROWSER. If a script must work on both desktop and headless machines, decide whether a non-zero result should stop the script rather than silently relying on a text-browser fallback.
sensible-browser resolves to the intended installed command and its sensible-utils version is known.BROWSER is a shell command string receiving the URL as an argument.printf stand-in that did not open a page.command -v before use.unset BROWSER, or by correcting its persistent source.