[GH-ISSUE #6058] Make whitelist handle symlinks in intermediate path #3169

Open
opened 2026-05-05 09:47:43 -06:00 by gitea-mirror · 14 comments
Owner

Originally created by @haarp on GitHub (Oct 20, 2023).
Original GitHub issue: https://github.com/netblue30/firejail/issues/6058

Discussed in https://github.com/netblue30/firejail/discussions/5980

Hello,

I'm seeing a problem with no easy solution when symlinks are involved.

Conditions:

  • You want to allow access to ~/.mozilla/firefox/profiles.ini, but nothing else in ~/.mozilla/
  • ~/.mozilla is a symlink to ~/Private/mozilla

The obvious solution is whitelist ${HOME}/.mozilla/firefox/profiles.ini. whitelist will descend down the path, see the .mozilla symlink and follow it, effectively whitelisting ~/Private/mozilla/profiles.ini. But the ~/.mozilla symlink, as expected by applications, is missing inside the jail!

Naive fix: Add whitelist ${HOME}/.mozilla. This will create the ~/.mozilla symlink. But it'll also whitelist all of ~/Private/mozilla/*! Not what we want.

I see no way of solving this with the currently available firejail directives. The implicit creation of jail symlinks by whitelist is not documented, and only works when it points to a symlink directly. From the manpage: Symbolic link handling: Whitelisting a path that is a symbolic link will also whitelist the path that it points to.

  • Solution 1: Add logic to whitelist. It currently follows symlinks as it descends down the path. Have it also create the symlinks in the jail for each followed link. TBD: Unexpected side effects?
  • Solution 2: Add a mklink directive, similar to how there already is a mkdir one. Easy fix, but hacky and inelegant.

Thanks!

Originally created by @haarp on GitHub (Oct 20, 2023). Original GitHub issue: https://github.com/netblue30/firejail/issues/6058 ### Discussed in https://github.com/netblue30/firejail/discussions/5980 Hello, I'm seeing a problem with no easy solution when symlinks are involved. Conditions: - You want to allow access to `~/.mozilla/firefox/profiles.ini`, but nothing else in `~/.mozilla/` - `~/.mozilla` is a symlink to `~/Private/mozilla` The obvious solution is `whitelist ${HOME}/.mozilla/firefox/profiles.ini`. whitelist will descend down the path, see the `.mozilla` symlink and follow it, effectively whitelisting `~/Private/mozilla/profiles.ini`. But the `~/.mozilla` symlink, as expected by applications, is missing inside the jail! Naive fix: Add `whitelist ${HOME}/.mozilla`. This **will** create the `~/.mozilla` symlink. But it'll also whitelist **all** of `~/Private/mozilla/*`! Not what we want. I see no way of solving this with the currently available firejail directives. The implicit creation of jail symlinks by `whitelist` is not documented, and only works when it points to a symlink directly. From the manpage: `Symbolic link handling: Whitelisting a path that is a symbolic link will also whitelist the path that it points to.` - Solution 1: Add logic to `whitelist`. It currently follows symlinks as it descends down the path. Have it also create the symlinks in the jail for each followed link. TBD: Unexpected side effects? - Solution 2: Add a `mklink` directive, similar to how there already is a `mkdir` one. Easy fix, but hacky and inelegant. Thanks!
gitea-mirror added the
enhancement
label 2026-05-05 09:47:43 -06:00
Author
Owner

@tolikzinovyev commented on GitHub (Mar 28, 2024):

I ran into the same issue.

<!-- gh-comment-id:2024299216 --> @tolikzinovyev commented on GitHub (Mar 28, 2024): I ran into the same issue.
Author
Owner

@ghost commented on GitHub (Mar 28, 2024):

@haarp

I've revisited your original discussion on this topic earlier today. Think I've found a working set of options for your custom discord setup. As this issue is not limited to discord I opted to post on that thread.

@tolikzinovyev

I ran into the same issue.

Can you please elaborate? Are you experiencing similar issues in discord as the OP? Somewhere else? AFAICT nobody is working on the suggested solutions (yet). It would be helpful if you could share a reproducer or provide some context here.

<!-- gh-comment-id:2025961979 --> @ghost commented on GitHub (Mar 28, 2024): @haarp I've revisited your original [discussion](#5980) on this topic earlier today. Think I've found a working set of options for your custom `discord setup`. As this issue is not limited to discord I opted to post on that thread. @tolikzinovyev > I ran into the same issue. Can you please elaborate? Are you experiencing similar issues in `discord` as the OP? Somewhere else? AFAICT nobody is working on the suggested solutions (yet). It would be helpful if you could share a reproducer or provide some context here.
Author
Owner

@tolikzinovyev commented on GitHub (Mar 28, 2024):

My troubles are limited to symlinks only. I have a folder ~/Downloads/firefox which I would like to whitelist where ~/Downloads is a symlink to ~/.homeextra. However, whitelist ${HOME}/Downloads/firefox doesn't create the necessary symlink in sandbox.

<!-- gh-comment-id:2026035469 --> @tolikzinovyev commented on GitHub (Mar 28, 2024): My troubles are limited to symlinks only. I have a folder `~/Downloads/firefox` which I would like to whitelist where `~/Downloads` is a symlink to `~/.homeextra`. However, `whitelist ${HOME}/Downloads/firefox` doesn't create the necessary symlink in sandbox.
Author
Owner

@ghost commented on GitHub (Mar 28, 2024):

@tolikzinovyev

The firefox-common.profile already whitelists ${DOWNLOADS}:

17684bb087/etc/profile-a-l/firefox-common.profile (L29)

How did you (try to) whitelist the symlinked ${HOME}/.homeextra exactly? What happens when you run firejail --whitelist=~/.homeextra /usr/bin/firefox?

<!-- gh-comment-id:2026142859 --> @ghost commented on GitHub (Mar 28, 2024): @tolikzinovyev The firefox-common.profile already whitelists ${DOWNLOADS}: https://github.com/netblue30/firejail/blob/17684bb087610f98cb5d033de4a9a099e827a0b0/etc/profile-a-l/firefox-common.profile#L29 How did you (try to) whitelist the symlinked `${HOME}/.homeextra` exactly? What happens when you run `firejail --whitelist=~/.homeextra /usr/bin/firefox`?
Author
Owner

@tolikzinovyev commented on GitHub (Mar 28, 2024):

Thanks, but this is not limited to firefox only.

I only have whitelist ${HOME}/Downloads/firefox. If I do firejail --whitelist=~/.homeextra /usr/bin/firefox, then all directories in .homeextra are accessible, not only Downloads. Oh, sorry, ~/Downloads is a symlink to ~/.homeextra/Downloads, not ~/.homeextra.

<!-- gh-comment-id:2026183754 --> @tolikzinovyev commented on GitHub (Mar 28, 2024): Thanks, but this is not limited to firefox only. I only have `whitelist ${HOME}/Downloads/firefox`. If I do `firejail --whitelist=~/.homeextra /usr/bin/firefox`, then all directories in `.homeextra` are accessible, not only `Downloads`. Oh, sorry, `~/Downloads` is a symlink to `~/.homeextra/Downloads`, not `~/.homeextra`.
Author
Owner

@ghost commented on GitHub (Mar 28, 2024):

@tolikzinovyev

All good. Your setup (and issue) is clearer to me now. I'll try to explain the 'logic' I've been using succesfully in situations like these. Feel free to shoot questions where needed. This isn't particularly straightforward, but it can be achieved safely IMO. Here goes.

  • [protect ~/.homeextra in all profiles]
    in globals.local
    blacklist ${HOME}/.homeextra

  • [selectively lift/grant access to ~/.homeextra in specific profile(s)]
    (these options apply for both blacklisting/whitelisting profiles)
    e.g. in firefox.local
    noblacklist ${HOME}/.homeextra
    # rule-of-thumb: allowed paths (via noblacklist) need to be handled
    # BEFORE protecting all others sub-dirs (via blacklist globbing)
    noblacklist ${HOME}/.homeextra/bar
    noblacklist ${HOME}/.homeextra/Downloads
    blacklist ${HOME}/.homeextra/*

  • [extra step for whitelisting profiles only]
    # selectively grant access to ~/.homeextra sub-dirs
    whitelist ${HOME}/.homeextra/bar
    whitelist ${HOME}/.homeextra/Downloads

That's it...

<!-- gh-comment-id:2026316103 --> @ghost commented on GitHub (Mar 28, 2024): @tolikzinovyev All good. Your setup (and issue) is clearer to me now. I'll try to explain the 'logic' I've been using succesfully in situations like these. Feel free to shoot questions where needed. This isn't particularly straightforward, but it can be achieved safely IMO. Here goes. - **[protect ~/.homeextra in all profiles]** in `globals.local` blacklist ${HOME}/.homeextra - **[selectively lift/grant access to ~/.homeextra in specific profile(s)]** (these options apply for both blacklisting/whitelisting profiles) e.g. in `firefox.local` noblacklist ${HOME}/.homeextra \# rule-of-thumb: allowed paths (via noblacklist) need to be handled \# BEFORE protecting all others sub-dirs (via blacklist globbing) noblacklist ${HOME}/.homeextra/bar noblacklist ${HOME}/.homeextra/Downloads blacklist ${HOME}/.homeextra/* - **[extra step for whitelisting profiles only]** \# selectively grant access to ~/.homeextra sub-dirs whitelist ${HOME}/.homeextra/bar whitelist ${HOME}/.homeextra/Downloads That's it...
Author
Owner

@tolikzinovyev commented on GitHub (Mar 29, 2024):

Thank you. This is a bit safer than what I do: I don't use blacklists here, only a whitelist. However, this doesn't solve the symlink issue. I would like to whitelist ${HOME}/.homeextra/Downloads/firefox but also get the path ~/Downloads/firefox to work.

<!-- gh-comment-id:2026351213 --> @tolikzinovyev commented on GitHub (Mar 29, 2024): Thank you. This is a bit safer than what I do: I don't use blacklists here, only a whitelist. However, this doesn't solve the symlink issue. I would like to whitelist `${HOME}/.homeextra/Downloads/firefox` but also get the path `~/Downloads/firefox` to work.
Author
Owner

@ghost commented on GitHub (Mar 29, 2024):

@tolikzinovyev

How about this?

# tested file layout
######################
~/.homeextra
~/.homeextra/Downloads
~/.homeextra/hide-me
~/Downloads -> /home/foo/.homeextra/Downloads
~/Downloads/firefox
~/Downloads/hide-me
######################

noblacklist ${HOME}/Downloads
noblacklist ${HOME}/Downloads/firefox
blacklist ${HOME}/Downloads/*

whitelist ${HOME}/Downloads
whitelist ${HOME}/.homeextra/Downloads

<!-- gh-comment-id:2026519848 --> @ghost commented on GitHub (Mar 29, 2024): @tolikzinovyev How about this? \# tested file layout \###################### ~/.homeextra ~/.homeextra/Downloads ~/.homeextra/hide-me ~/Downloads -> /home/foo/.homeextra/Downloads ~/Downloads/firefox ~/Downloads/hide-me \###################### noblacklist ${HOME}/Downloads noblacklist ${HOME}/Downloads/firefox blacklist ${HOME}/Downloads/* whitelist ${HOME}/Downloads whitelist ${HOME}/.homeextra/Downloads
Author
Owner

@tolikzinovyev commented on GitHub (Mar 29, 2024):

Thank you for the suggestion. I see two problems with it.

  1. Files added in ~/Downloads/ while the sandbox is running will be accessible in the sandbox.
  2. The directory listing of ~/Downloads/ is accessible in the sandbox.
<!-- gh-comment-id:2027463891 --> @tolikzinovyev commented on GitHub (Mar 29, 2024): Thank you for the suggestion. I see two problems with it. 1. Files added in `~/Downloads/` while the sandbox is running will be accessible in the sandbox. 2. The directory listing of `~/Downloads/` is accessible in the sandbox.
Author
Owner

@ghost commented on GitHub (Mar 29, 2024):

Files added in ~/Downloads/ while the sandbox is running will be accessible in the sandbox.

Correct. I don't see a way around that when symlinking ~/Downloads to ~/.homeextra/Downloads.

The directory listing of ~/Downloads/ is accessible in the sandbox.

Also correct. This happens in lots of profiles. When file access is actually prohibited IMO that's not much of a security issue. Ideal? No. Highly unsafe? IMO not really.

Very likely there are cleaner/tighter/safer alternatives. If you could elaborate what the intended goal is of having a symlinked ~/Downloads/firefox to another location under ~ this symlink spagetti might be avoided. If the goal is to have a dedicated folder for Firefox to access, maybe you can set it in its prefs? I mean, why not point it directly to ~/.homeextra/Downloads/firefox and control it via a one-liner whitelist ~/.homeextra/Downloads/firefox?

<!-- gh-comment-id:2027549173 --> @ghost commented on GitHub (Mar 29, 2024): > Files added in ~/Downloads/ while the sandbox is running will be accessible in the sandbox. Correct. I don't see a way around that when symlinking ~/Downloads to ~/.homeextra/Downloads. > The directory listing of ~/Downloads/ is accessible in the sandbox. Also correct. This happens in lots of profiles. When file access is actually prohibited IMO that's not much of a security issue. Ideal? No. Highly unsafe? IMO not really. Very likely there are cleaner/tighter/safer alternatives. If you could elaborate what the intended goal is of having a symlinked ~/Downloads/firefox to another location under ~ this symlink spagetti might be avoided. If the goal is to have a dedicated folder for Firefox to access, maybe you can set it in its prefs? I mean, why not point it directly to `~/.homeextra/Downloads/firefox` and control it via a one-liner `whitelist ~/.homeextra/Downloads/firefox`?
Author
Owner

@tolikzinovyev commented on GitHub (Mar 29, 2024):

Yes, I set the download location to ~/.homeextra/Downloads/firefox in Firefox settings. It works but other applications like signal-desktop ask the location every time. In the file picker I first have to enable hidden files to display .homeextra which is several extra clicks. I'm not saying it breaks my setup, but it is an annoyance.

<!-- gh-comment-id:2027612692 --> @tolikzinovyev commented on GitHub (Mar 29, 2024): Yes, I set the download location to `~/.homeextra/Downloads/firefox` in Firefox settings. It works but other applications like signal-desktop ask the location every time. In the file picker I first have to enable hidden files to display `.homeextra` which is several extra clicks. I'm not saying it breaks my setup, but it is an annoyance.
Author
Owner

@ghost commented on GitHub (Mar 29, 2024):

The default XDG locations are stored in ~/.config/user-dirs.dirs, which is made read-only in disable-common.inc and part of whitelist-common.inc. So for most GUI profiles that should be accessable without having to touch the profiles. Have you tried setting XDG_DOWNLOAD_DIR="$HOME/.homeextra/Downloads/firefox" in that file yet? Alternatively you could add it to ~/.config/gtk-{3,4}.0/bookmarks for ease-of-use in the file picker.

<!-- gh-comment-id:2027751219 --> @ghost commented on GitHub (Mar 29, 2024): The default XDG locations are stored in `~/.config/user-dirs.dirs`, which is made read-only in disable-common.inc and part of whitelist-common.inc. So for most GUI profiles that should be accessable without having to touch the profiles. Have you tried setting XDG_DOWNLOAD_DIR="$HOME/.homeextra/Downloads/firefox" in that file yet? Alternatively you could add it to `~/.config/gtk-{3,4}.0/bookmarks` for ease-of-use in the file picker.
Author
Owner

@tolikzinovyev commented on GitHub (Mar 30, 2024):

The bookmarks method worked, thank you!

<!-- gh-comment-id:2027889592 --> @tolikzinovyev commented on GitHub (Mar 30, 2024): The bookmarks method worked, thank you!
Author
Owner

@tolikzinovyev commented on GitHub (Jun 19, 2024):

I ran into this issue again. Here is the scenario. I browse files with Thunar and open a picture in ~/Downloads/firefox with eom (eye of mate). Since in eom profile I only have whitelist ${HOME}/Downloads/firefox, eom can't open the picture. This problem is pretty annoying and a fix would be greatly appreciated!

<!-- gh-comment-id:2177354346 --> @tolikzinovyev commented on GitHub (Jun 19, 2024): I ran into this issue again. Here is the scenario. I browse files with Thunar and open a picture in `~/Downloads/firefox` with `eom` (eye of mate). Since in `eom` profile I only have `whitelist ${HOME}/Downloads/firefox`, `eom` can't open the picture. This problem is pretty annoying and a fix would be greatly appreciated!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#3169
No description provided.