[GH-ISSUE #903] mkdir in profile does not respect --private=<directory> #611

Open
opened 2026-05-05 06:16:23 -06:00 by gitea-mirror · 20 comments
Owner

Originally created by @pyamsoft on GitHub (Nov 9, 2016).
Original GitHub issue: https://github.com/netblue30/firejail/issues/903

Latest stable firejail: 0.9.44

The command line option --private=<directory> states that firejail uses the given directory as a new home.

--private=directory
      Use directory as user home.

      Example:
      $ firejail --private=/home/netblue/firefox-home firefox

This works fine, and all whitelist and blacklist commands work as expected with respect to the private directory. However, using mkdir in a profile incorrectly creates the directory in the real home.

You can observe this in the shipped Dropbox profile for example, which makes calls to mkdir in its profile:

firejail --private=/home/pyamsoft/dropboxtesting dropbox

You can observe similar errors in the shipped firefox profile.

firejail --private=/home/pyamsoft/firefoxtesting firefox

You will see that a Dropbox folder will be created in the actual home directory, instead of the private home at ~/dropboxtesting. You will also see the firefox directories like ~/.mozilla being created in the real home. I would expect that mkdir will respect the private home directory just as whitelist and blacklist do, so I believe this behavior to be a bug.

Originally created by @pyamsoft on GitHub (Nov 9, 2016). Original GitHub issue: https://github.com/netblue30/firejail/issues/903 Latest stable firejail: 0.9.44 The command line option `--private=<directory>` states that firejail uses the given directory as a new home. ``` --private=directory Use directory as user home. Example: $ firejail --private=/home/netblue/firefox-home firefox ``` This works fine, and all whitelist and blacklist commands work as expected with respect to the private directory. However, using mkdir in a profile incorrectly creates the directory in the real home. You can observe this in the shipped Dropbox profile for example, which makes calls to mkdir in its profile: ``` firejail --private=/home/pyamsoft/dropboxtesting dropbox ``` You can observe similar errors in the shipped firefox profile. ``` firejail --private=/home/pyamsoft/firefoxtesting firefox ``` You will see that a Dropbox folder will be created in the actual home directory, instead of the private home at ~/dropboxtesting. You will also see the firefox directories like ~/.mozilla being created in the real home. I would expect that mkdir will respect the private home directory just as whitelist and blacklist do, so I believe this behavior to be a bug.
gitea-mirror added the
enhancement
label 2026-05-05 06:16:23 -06:00
Author
Owner

@valoq commented on GitHub (Nov 9, 2016):

I can confirm the behaviour. Seems like a bug to me.

<!-- gh-comment-id:259397673 --> @valoq commented on GitHub (Nov 9, 2016): I can confirm the behaviour. Seems like a bug to me.
Author
Owner

@netblue30 commented on GitHub (Nov 10, 2016):

Fixed, thanks for the bug.

<!-- gh-comment-id:259697270 --> @netblue30 commented on GitHub (Nov 10, 2016): Fixed, thanks for the bug.
Author
Owner

@okcomputerik commented on GitHub (Mar 4, 2017):

Although marked as fixed, I see the same behavior running firejail 0.9.44.8 with the dropbox profile. Am I missing something here? Thanks!

<!-- gh-comment-id:284169534 --> @okcomputerik commented on GitHub (Mar 4, 2017): Although marked as fixed, I see the same behavior running firejail 0.9.44.8 with the dropbox profile. Am I missing something here? Thanks!
Author
Owner

@netblue30 commented on GitHub (Mar 5, 2017):

I'll look into it, thanks.

<!-- gh-comment-id:284228624 --> @netblue30 commented on GitHub (Mar 5, 2017): I'll look into it, thanks.
Author
Owner

@sunho0301 commented on GitHub (Apr 10, 2017):

Are there any updates on this issue?? I'm having the same problem.
Thanks!

<!-- gh-comment-id:293107662 --> @sunho0301 commented on GitHub (Apr 10, 2017): Are there any updates on this issue?? I'm having the same problem. Thanks!
Author
Owner

@chiraag-nataraj commented on GitHub (Jul 15, 2018):

Is this still an issue? If so, let's figure out what's going on :)

<!-- gh-comment-id:405119409 --> @chiraag-nataraj commented on GitHub (Jul 15, 2018): Is this still an issue? If so, let's figure out what's going on :)
Author
Owner

@chiraag-nataraj commented on GitHub (Jul 30, 2018):

Yes, this is still an issue. The question becomes the following:
If we write mkdir ${HOME}/<somedir>, do we mean the real ${HOME} or what the sandbox will see as ${HOME}?

<!-- gh-comment-id:408887190 --> @chiraag-nataraj commented on GitHub (Jul 30, 2018): Yes, this is still an issue. The question becomes the following: If we write `mkdir ${HOME}/<somedir>`, do we mean the _real_ `${HOME}` or what the _sandbox_ will see as `${HOME}`?
Author
Owner

@chiraag-nataraj commented on GitHub (Aug 1, 2018):

@netblue30 Is this intended behavior? If we use ${HOME} in, say, mkdir, do we want ${HOME} to be resolved after things like --private have been resolved or do we want to resolve it before those predicates? That will change the behavior as I understand it, and either one is fine as long as we document it.

<!-- gh-comment-id:409600638 --> @chiraag-nataraj commented on GitHub (Aug 1, 2018): @netblue30 Is this intended behavior? If we use `${HOME}` in, say, `mkdir`, do we want `${HOME}` to be resolved _after_ things like `--private` have been resolved or do we want to resolve it _before_ those predicates? That will change the behavior as I understand it, and either one is fine as long as we document it.
Author
Owner

@chiraag-nataraj commented on GitHub (May 21, 2019):

Sorry to dredge up so many old issues, but @netblue30, is this intended behavior? If so, we can close. Otherwise, we should fix this.

<!-- gh-comment-id:494213072 --> @chiraag-nataraj commented on GitHub (May 21, 2019): Sorry to dredge up so many old issues, but @netblue30, is this intended behavior? If so, we can close. Otherwise, we should fix this.
Author
Owner

@matu3ba commented on GitHub (Apr 9, 2020):

@rusty-snake @chiraag-nataraj
If the folder does not exist, firejail prompts Error: invalid private directory and exists. If nesting of firejails is forbidden, the error could maybe be simplified to Error: folder not usable as private directory. However I am not sure about this.
Otherwise suggestion to close this.

<!-- gh-comment-id:611527192 --> @matu3ba commented on GitHub (Apr 9, 2020): @rusty-snake @chiraag-nataraj If the folder does not exist, firejail prompts `Error: invalid private directory` and exists. If nesting of firejails is [forbidden](https://github.com/netblue30/firejail/issues/3333#issuecomment-611510025), the error could maybe be simplified to `Error: folder not usable as private directory`. However I am not sure about this. Otherwise suggestion to close this.
Author
Owner

@rusty-snake commented on GitHub (Apr 9, 2020):

@matu3ba it's not about the private directory does not work. The mkdir does not respect it. Like this:

$ cat tmp.profile
mkdir ${HOME}/foo
private
mkdir ${HOME}/bar
$ firejail --profile=tmp.profile true
$ [ -e foo ] && echo "foo exists"
foo exists
$ [ -e bar ] && echo "bar exists"
bar exists
<!-- gh-comment-id:611548137 --> @rusty-snake commented on GitHub (Apr 9, 2020): @matu3ba it's not about the private directory does not work. The mkdir does not respect it. Like this: ``` $ cat tmp.profile mkdir ${HOME}/foo private mkdir ${HOME}/bar $ firejail --profile=tmp.profile true $ [ -e foo ] && echo "foo exists" foo exists $ [ -e bar ] && echo "bar exists" bar exists ```
Author
Owner

@vinc17fr commented on GitHub (Oct 19, 2021):

In fact, mkdir creates a directory in both the real home directory and the sandbox. And mkfile has the same issue:

$ cat > .config/firejail/test.profile
mkdir ${HOME}/fj-dir
mkfile ${HOME}/fj-file
$ mkdir fj-priv
$ ls -d fj-dir fj-file fj-priv/*
ls: cannot access 'fj-dir': No such file or directory
ls: cannot access 'fj-file': No such file or directory
ls: cannot access 'fj-priv/*': No such file or directory
$ firejail --private=fj-priv --profile=test sh
Reading profile /home/vinc17/.config/firejail/test.profile
Parent pid 52414, child pid 52417
Child process initialized in 12.93 ms
$ exit
sh: 1: Cannot set tty process group (No such process)

Parent is shutting down, bye...
$ ls -d fj-dir fj-file fj-priv/*
fj-dir  fj-file  fj-priv/fj-dir  fj-priv/fj-file
<!-- gh-comment-id:946576177 --> @vinc17fr commented on GitHub (Oct 19, 2021): In fact, `mkdir` creates a directory in _both_ the real home directory and the sandbox. And `mkfile` has the same issue: ``` $ cat > .config/firejail/test.profile mkdir ${HOME}/fj-dir mkfile ${HOME}/fj-file $ mkdir fj-priv $ ls -d fj-dir fj-file fj-priv/* ls: cannot access 'fj-dir': No such file or directory ls: cannot access 'fj-file': No such file or directory ls: cannot access 'fj-priv/*': No such file or directory $ firejail --private=fj-priv --profile=test sh Reading profile /home/vinc17/.config/firejail/test.profile Parent pid 52414, child pid 52417 Child process initialized in 12.93 ms $ exit sh: 1: Cannot set tty process group (No such process) Parent is shutting down, bye... $ ls -d fj-dir fj-file fj-priv/* fj-dir fj-file fj-priv/fj-dir fj-priv/fj-file ```
Author
Owner

@smitsohu commented on GitHub (Oct 19, 2021):

To illustrate what probably was the reasoning behind this design, let's take Firefox. The profile uses whitelist in user home, so if the program is never run outside of Firejail, all application files and directories (~/.mozilla, ~/.cache/mozilla, ...) are ever created only in the tmpfs, and are always discarded when the sandbox shuts down. There will never be any persistence, which is not how whitelist is supposed to work, and is closer to what private is supposed to do.

One possible solution is to create needed files and directories beforehand as the user in the real file system, so that whitelist can properly bind mount them in the sandbox.

The downside is that some profiles create quite a clutter in the file system, which is also not so nice. As a workaround you can add

ignore mkfile
ignore mkdir

to /etc/firejail/globals.local and create files manually, or run applications once outside Firejail, which is usually sufficient to get all required directories and files.

<!-- gh-comment-id:946673346 --> @smitsohu commented on GitHub (Oct 19, 2021): To illustrate what probably was the reasoning behind this design, let's take Firefox. The profile uses `whitelist` in user home, so if the program is _never_ run outside of Firejail, all application files and directories (`~/.mozilla`, `~/.cache/mozilla`, ...) are ever created only in the tmpfs, and are _always_ discarded when the sandbox shuts down. There will never be any persistence, which is not how `whitelist` is supposed to work, and is closer to what `private` is supposed to do. One possible solution is to create needed files and directories beforehand as the user in the real file system, so that `whitelist` can properly bind mount them in the sandbox. The downside is that some profiles create quite a clutter in the file system, which is also not so nice. As a workaround you can add ``` ignore mkfile ignore mkdir ``` to `/etc/firejail/globals.local` and create files manually, or run applications once outside Firejail, which is usually sufficient to get all required directories and files.
Author
Owner

@rusty-snake commented on GitHub (Oct 19, 2021):

FTR: #4285

<!-- gh-comment-id:946676580 --> @rusty-snake commented on GitHub (Oct 19, 2021): FTR: #4285
Author
Owner

@smitsohu commented on GitHub (Oct 19, 2021):

Maybe we could postpone mkdir and mkfileuntil after private option processing, but handle them before whitelist.

<!-- gh-comment-id:946695066 --> @smitsohu commented on GitHub (Oct 19, 2021): Maybe we could postpone `mkdir` and `mkfile`until after private option processing, but handle them before `whitelist`.
Author
Owner

@colons commented on GitHub (Dec 20, 2023):

hi. i don't know that this issue has any actual security consequences, but it is extremely disconcerting to see your home directory littered with directories related to something you launched with the promise that it'd be contained to a directory you specified. if nothing else, it's a violation of what --private says it'll do, and it requires active tidying up after it has its effect

<!-- gh-comment-id:1864606649 --> @colons commented on GitHub (Dec 20, 2023): hi. i don't know that this issue has any actual security consequences, but it is _extremely_ disconcerting to see your home directory littered with directories related to something you launched with the promise that it'd be contained to a directory you specified. if nothing else, it's a violation of what `--private` says it'll do, and it requires active tidying up after it has its effect
Author
Owner

@spikethehobbitmage commented on GitHub (Jan 4, 2025):

Maybe we could postpone mkdir and mkfileuntil after private option processing, but handle them before whitelist.

This is exactly what needs to happen. overlay options should* also be processed before mk* since they also discard jailed changes.

*This may already be the case but overlay is disabled on my system so I can't test it.

<!-- gh-comment-id:2570004479 --> @spikethehobbitmage commented on GitHub (Jan 4, 2025): > Maybe we could postpone `mkdir` and `mkfile`until after private option processing, but handle them before `whitelist`. This is exactly what needs to happen. `overlay` options should* also be processed before `mk*` since they also discard jailed changes. *This may already be the case but `overlay` is disabled on my system so I can't test it.
Author
Owner

@giddie commented on GitHub (Jul 7, 2025):

This is disconcerting, and I'm trying to understand the scope of the issue. If I do this:

$ mkdir ~/jail
$ firejail --private=~/jail bash -c "mkdir ~/another"
$ ls ~/jail
another
$ ls ~/another
ls: cannot access '/home/user/another`: No such file or directory

So it actually seems to be working correctly. How do we reproduce the bug?

<!-- gh-comment-id:3044544685 --> @giddie commented on GitHub (Jul 7, 2025): This is disconcerting, and I'm trying to understand the scope of the issue. If I do this: ```bash $ mkdir ~/jail $ firejail --private=~/jail bash -c "mkdir ~/another" $ ls ~/jail another $ ls ~/another ls: cannot access '/home/user/another`: No such file or directory ``` So it actually seems to be working correctly. How do we reproduce the bug?
Author
Owner

@tanriol commented on GitHub (Jul 7, 2025):

How do we reproduce the bug?

firejail --private=~/jail --mkdir=~/another bash -c "true"

This looks kinda stupid when both are specified on the command line - why do we need mkdir in a private profile - but when one is mkdir in steam.profile (dozens of them are there) and the other is --private=${HOME}/steam-jail in the script used to launch Steam, the fact that it still creates dirs in real home like ${HOME}/Zomboid (not even a hidden one!) feels plain wrong.

<!-- gh-comment-id:3044927896 --> @tanriol commented on GitHub (Jul 7, 2025): > How do we reproduce the bug? `firejail --private=~/jail --mkdir=~/another bash -c "true"` This looks kinda stupid when both are specified on the command line - why do we need `mkdir` in a private profile - but when one is `mkdir` in `steam.profile` (dozens of them are there) and the other is `--private=${HOME}/steam-jail` in the script used to launch Steam, the fact that it still creates dirs in real home like `${HOME}/Zomboid` (not even a hidden one!) feels plain wrong.
Author
Owner

@giddie commented on GitHub (Jul 7, 2025):

Aaaaah! 💡 This is a lot less concerning than the manpage suggests. When it says "some commands such as mkdir ...", what I understood was that mkdir inside the container was broken. OK, this is not such a huge deal. But the bug warning could maybe better communicate that it's just referring to firejail command-line arguments or commands in profiles.

<!-- gh-comment-id:3046374434 --> @giddie commented on GitHub (Jul 7, 2025): Aaaaah! 💡 This is a _lot_ less concerning than the manpage suggests. When it says "some *commands* such as mkdir ...", what I understood was that `mkdir` _inside_ the container was broken. OK, this is not such a huge deal. But the bug warning could maybe better communicate that it's just referring to firejail command-line arguments or commands in _profiles_.
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#611
No description provided.