[GH-ISSUE #2202] Need better way of managing order of options vis-a-vis implicitly-loaded profiles #1476

Open
opened 2026-05-05 08:08:26 -06:00 by gitea-mirror · 9 comments
Owner

Originally created by @iskunk on GitHub (Oct 18, 2018).
Original GitHub issue: https://github.com/netblue30/firejail/issues/2202

As I understand it, Firejail processes command-line options and profile-file directives in the order that they appear on the command line (with profiles based on the name of the program implicitly appearing at the end). The order is significant in many cases, with the correct jail behavior resulting only if the directives are ordered correctly.

An example of this ordering is the hostname directive. Say that you want to run a program named hello, with a Firejail profile /etc/firejail/hello.profile. This profile contains a hostname hello-machine line.

If I run firejail hello, then the program sees a hostname of hello-machine, as expected.

If I run firejail --hostname=goodbye-machine hello, then the program still sees a hostname of hello-machine. The hello.profile file is loaded after the --hostname option is processed, and the hostname hello-machine directive effectively "overwrites" the value previously set on the command line.

Now, if I run firejail --profile=/etc/firejail/hello.profile --hostname=goodbye-machine hello, then and only then does the program get goodbye-machine. Because the --hostname option now comes after the directive in the profile.

But in order to get that desired behavior, I have to give up the implicit profile load, and instead load the profile explicitly. Wouldn't it be nice if I could specify that I want --hostname (or whatever other option) to be processed after the profile, but without having to change how the profiles are specified?

For example, an invocation like firejail --after-profile --hostname=goodbye-machine hello, in which a special option (--after-profile) indicates that all subsequent options should be processed after the profile is loaded.

After discovering through experimentation the importance of the order in which Firejail options are processed, I'd want something like this to help make it easier to get that right.

Originally created by @iskunk on GitHub (Oct 18, 2018). Original GitHub issue: https://github.com/netblue30/firejail/issues/2202 As I understand it, Firejail processes command-line options and profile-file directives in the order that they appear on the command line (with profiles based on the name of the program implicitly appearing at the end). The order is significant in many cases, with the correct jail behavior resulting only if the directives are ordered correctly. An example of this ordering is the `hostname` directive. Say that you want to run a program named `hello`, with a Firejail profile `/etc/firejail/hello.profile`. This profile contains a `hostname hello-machine` line. If I run `firejail hello`, then the program sees a hostname of `hello-machine`, as expected. If I run `firejail --hostname=goodbye-machine hello`, then the program *still* sees a hostname of `hello-machine`. The `hello.profile` file is loaded after the `--hostname` option is processed, and the `hostname hello-machine` directive effectively "overwrites" the value previously set on the command line. Now, if I run `firejail --profile=/etc/firejail/hello.profile --hostname=goodbye-machine hello`, *then* and only then does the program get `goodbye-machine`. Because the `--hostname` option now comes *after* the directive in the profile. But in order to get that desired behavior, I have to give up the implicit profile load, and instead load the profile explicitly. Wouldn't it be nice if I could specify that I want `--hostname` (or whatever other option) to be processed after the profile, but without having to change how the profiles are specified? For example, an invocation like `firejail --after-profile --hostname=goodbye-machine hello`, in which a special option (`--after-profile`) indicates that all subsequent options should be processed after the profile is loaded. After discovering through experimentation the importance of the order in which Firejail options are processed, I'd want something like this to help make it easier to get that right.
gitea-mirror added the
enhancement
label 2026-05-05 08:08:26 -06:00
Author
Owner

@Vincent43 commented on GitHub (Oct 18, 2018):

firejail --hostname=goodbye-machine --ignore=hostname hello should do what you want therefore I don't think --after-profile is much improvement and worth additional complexity. After brief look I didn't find any other option affected by ordering.

<!-- gh-comment-id:430960676 --> @Vincent43 commented on GitHub (Oct 18, 2018): `firejail --hostname=goodbye-machine --ignore=hostname hello` should do what you want therefore I don't think `--after-profile` is much improvement and worth additional complexity. After brief look I didn't find any other option affected by ordering.
Author
Owner

@iskunk commented on GitHub (Oct 18, 2018):

I only chose hostname as a simple example to demonstrate ordering of directives. There are more complex scenarios, like interactions between noblacklist, whitelist and read-only for a given directory, where the ignore directive does little to help.

<!-- gh-comment-id:431072489 --> @iskunk commented on GitHub (Oct 18, 2018): I only chose `hostname` as a simple example to demonstrate ordering of directives. There are more complex scenarios, like interactions between `noblacklist`, `whitelist` and `read-only` for a given directory, where the `ignore` directive does little to help.
Author
Owner

@Vincent43 commented on GitHub (Oct 18, 2018):

Can you give example commands which doesn't work as expected?

<!-- gh-comment-id:431095898 --> @Vincent43 commented on GitHub (Oct 18, 2018): Can you give example commands which doesn't work as expected?
Author
Owner

@iskunk commented on GitHub (Oct 18, 2018):

One example is --read-only versus --read-write. If you want to make everything under ~/.config/ read-only except for one directory ~/.config/foo/, then Firejail needs to see

read-only ~/.config
read-write ~/.config/foo

in that order, as the reverse will not work (the foo directory remains read-only). So if, say, the default profile has a read-only directive for a given directory, and you want to make a subdirectory writable, then you run into this problem.

An alternative course of action might be to treat ordering dependencies like this as a bug (outside of perhaps noblacklist, ignore, and a few other directives that are usually meant to come first) and ensure the same result regardless of order, but I don't know if that might have negative security implications. (In the above example, it could be advisable to print a warning like Making ~/.config read-only, but ~/.config/foo was previously made read-write)

<!-- gh-comment-id:431191966 --> @iskunk commented on GitHub (Oct 18, 2018): One example is `--read-only` versus `--read-write`. If you want to make everything under `~/.config/` read-only except for one directory `~/.config/foo/`, then Firejail needs to see ``` read-only ~/.config read-write ~/.config/foo ``` in that order, as the reverse will not work (the `foo` directory remains read-only). So if, say, the default profile has a `read-only` directive for a given directory, and you want to make a subdirectory writable, then you run into this problem. An alternative course of action might be to treat ordering dependencies like this as a bug (outside of perhaps `noblacklist`, `ignore`, and a few other directives that are usually meant to come first) and ensure the same result regardless of order, but I don't know if that might have negative security implications. (In the above example, it could be advisable to print a warning like `Making ~/.config read-only, but ~/.config/foo was previously made read-write`)
Author
Owner

@Vincent43 commented on GitHub (Oct 19, 2018):

In above passing firejail --read-only=~/.config --read-write=~/.config/foo should be enough as duplicate --read-only ~/.config from profile won't take effect after that.

Maybe others have any ideas if this syntax can be somewhat improved.

<!-- gh-comment-id:431326967 --> @Vincent43 commented on GitHub (Oct 19, 2018): In above passing `firejail --read-only=~/.config --read-write=~/.config/foo` should be enough as duplicate `--read-only ~/.config` from profile won't take effect after that. Maybe others have any ideas if this syntax can be somewhat improved.
Author
Owner

@iskunk commented on GitHub (Oct 19, 2018):

Having to put in redundant directives isn't a great approach. And if you're using the same options for different programs, which might have different profiles, then you get a read-only ~/.config whether or not the profile marks it as such.

A second read-only on the same directory is a no-op, then? That sounds like a partial fulfillment of making the profile directives independent of order...

<!-- gh-comment-id:431419706 --> @iskunk commented on GitHub (Oct 19, 2018): Having to put in redundant directives isn't a great approach. And if you're using the same options for different programs, which might have different profiles, then you get a read-only `~/.config` whether or not the profile marks it as such. A second `read-only` on the same directory is a no-op, then? That sounds like a partial fulfillment of making the profile directives independent of order...
Author
Owner

@Vincent43 commented on GitHub (Oct 19, 2018):

I just wanted to point out that if someone is looking for a working solution then it exists. Setting it through .local profiles may be also less burdensome.

<!-- gh-comment-id:431469220 --> @Vincent43 commented on GitHub (Oct 19, 2018): I just wanted to point out that if someone is looking for a working solution then it exists. Setting it through `.local` profiles may be also less burdensome.
Author
Owner

@iskunk commented on GitHub (Oct 19, 2018):

That's fair; just remember that the original issue was not that certain setups are impossible, only that the config model is awkward in some cases (due to ordering) and could stand some improvement. If one doesn't mind e.g. writing a profile for every possible permutation of options needed, then this won't be an issue, but I'd like to see more flexibility to the end result of conciseness and reduced redundancy in the configuration. (Which tends to be a net positive for security, too.)

<!-- gh-comment-id:431524220 --> @iskunk commented on GitHub (Oct 19, 2018): That's fair; just remember that the original issue was not that certain setups are impossible, only that the config model is awkward in some cases (due to ordering) and could stand some improvement. If one doesn't mind e.g. writing a profile for every possible permutation of options needed, then this won't be an issue, but I'd like to see more flexibility to the end result of conciseness and reduced redundancy in the configuration. (Which tends to be a net positive for security, too.)
Author
Owner

@moll commented on GitHub (Mar 31, 2020):

I'd like to double what was said above about the configuration order. I don't think the entire current backwards system makes much sense compared to the far more prevalent last-set-wins. Firejail's awkward backwardness can be seen best in global profiles that need to load local ones before their own settings, expecting local configuration to possibly ignore changes that follow. Presumably that's why the command line arguments are run before the profile options, too, which prompted @iskunk to report the problem here. The backwardness makes for rather peculiar if not outright impossible situations where occasionally you'll need to ignore a later ignore... Not to mention configuration files are often loaded backwards and inwards as overrides need to appear prior to defaults. Looking at a random profile, makepkg.profile, for example, shows how makepkg.local is loaded before globals.local, yet both are loaded before options in makepkg.profile itself. That's very confusing.

While there are a large number of existing profiles, I'd say it's worth simplifying the configuration semantics early. Usability improvements, even if they introduce temporary inconvenience, are worth in the long term. I'd suggest following what the majority of other configuration languages do, and that's reading configuration files top to bottom, with any new directive overwriting previously set values. One defaults.profile could be loaded at the top to provide a shared baseline. Local overrides would be loaded at the end of the file. The ignore pragma could be removed entirely. So could any warnings about reconfiguring previously set values, as honoring the latest setting would be the way to tweak global profiles. The same should apply to command line arguments, removing the need for the rather silly firejail --hostname=goodbye-machine --ignore=hostname hello workaround.

<!-- gh-comment-id:606773998 --> @moll commented on GitHub (Mar 31, 2020): I'd like to double what was said above about the configuration order. I don't think the entire current **backwards system** makes much sense compared to the far more prevalent **last-set-wins**. Firejail's awkward backwardness can be seen best in global profiles that need to load local ones _before_ their own settings, expecting local configuration to possibly `ignore` changes that follow. Presumably that's why the command line arguments are run _before_ the profile options, too, which prompted @iskunk to report the problem here. The backwardness makes for rather peculiar if not outright impossible situations where occasionally you'll need to `ignore` a later `ignore`... Not to mention configuration files are often loaded backwards and inwards as overrides need to appear _prior_ to defaults. Looking at a random profile, `makepkg.profile`, for example, shows how `makepkg.local` is loaded before `globals.local`, yet both are loaded before options in `makepkg.profile` itself. That's very confusing. While there are a large number of existing profiles, I'd say it's worth simplifying the configuration semantics early. Usability improvements, even if they introduce temporary inconvenience, are worth in the long term. I'd suggest following what the majority of other configuration languages do, and that's reading configuration files top to bottom, with any new directive overwriting previously set values. One `defaults.profile` could be loaded at the top to provide a shared baseline. Local overrides would be loaded at the end of the file. The `ignore` pragma could be removed entirely. So could any warnings about reconfiguring previously set values, as honoring the latest setting would be the way to tweak global profiles. The same should apply to command line arguments, removing the need for the rather silly `firejail --hostname=goodbye-machine --ignore=hostname hello` workaround.
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#1476
No description provided.