[GH-ISSUE #7078] AppArmor profile does not grant userns permissions #3479

Open
opened 2026-05-05 10:01:32 -06:00 by gitea-mirror · 7 comments
Owner

Originally created by @cobratbq on GitHub (Feb 25, 2026).
Original GitHub issue: https://github.com/netblue30/firejail/issues/7078

Description

Is AppArmor not granted userns privileges when running within AppArmor?

Newer AppArmor versions have a userns permission that allows access to user-namespaces when these are otherwise restricted. The profile firejail-default does not set this permission.

I suspect this inhibits the capabilities of firejail itself. The issue, but specifically for firefox, is also discussed in #6675.

Steps to Reproduce

  1. Run /usr/bin/firejail --debug /usr/bin/firefox --no-remote (without making any changes)
  2. Notice an error message [56] Sandbox: CanCreateUserNamespace() clone() failure: EACCESS.

Expected behavior

No error-message.

Actual behavior

Application starts, but is restricted from anything concerning user-namespaces even if not restricted by firejail options/profiles, because firejail itself is restricted.

Behavior without a profile

Not tested. Adding userns to /etc/apparmor.d/firejail-default already solves the problem, i.e. makes the difference.

Additional context

From reading other information, i.e. #6675, I gather this is a recent change/feature in AppArmor 4, which I guess is in Debian.

This effectively weakens Firefox's inherent sandboxing capabilities because they are restricted from using user-namespaces. It also seems that user-namespaces provide value with Firefox's sandboxing capacity.

Also, given that subsequently capabilities are dropped, there should be reduced risk even if user-namespaces are in use.(?)

Environment

  • Debian trixie
  • 6.12.73+deb13-amd64
  • AppArmor enforced for firejail

Checklist

  • I am using firejail 0.9.78 or later
  • I am using the full program path (e.g. firejail /usr/bin/vlc instead of firejail vlc; see https://github.com/netblue30/firejail/issues/2877)
  • The issues is caused by firejail (i.e. running the program by path (e.g. /usr/bin/vlc) "fixes" it).
  • I can reproduce the issue without custom modifications (e.g. globals.local).
  • The program has a profile. (If not, request one in https://github.com/netblue30/firejail/issues/1139)
  • The profile (and redirect profile if exists) hasn't already been fixed upstream.
  • I have performed a short search for similar issues (to avoid opening a duplicate).
    • I'm aware of browser-allow-drm yes/browser-disable-u2f no in firejail.config to allow DRM/U2F in browsers.
  • I used --profile=PROFILENAME to set the right profile. (Only relevant for AppImages)

Log

N/A

Originally created by @cobratbq on GitHub (Feb 25, 2026). Original GitHub issue: https://github.com/netblue30/firejail/issues/7078 ### Description Is AppArmor not granted `userns` privileges when running within AppArmor? Newer AppArmor versions have a `userns` permission that allows access to user-namespaces when these are otherwise restricted. The profile `firejail-default` does not set this permission. I suspect this inhibits the capabilities of `firejail` itself. The issue, but specifically for firefox, is also discussed in #6675. ### Steps to Reproduce 1. Run `/usr/bin/firejail --debug /usr/bin/firefox --no-remote` (without making any changes) 2. Notice an error message `[56] Sandbox: CanCreateUserNamespace() clone() failure: EACCESS`. ### Expected behavior No error-message. ### Actual behavior Application starts, but is restricted from anything concerning user-namespaces even if not restricted by firejail options/profiles, because firejail itself is restricted. ### Behavior without a profile Not tested. Adding `userns` to `/etc/apparmor.d/firejail-default` already solves the problem, i.e. makes the difference. ### Additional context From reading other information, i.e. #6675, I gather this is a recent change/feature in AppArmor 4, which I guess is in Debian. This effectively weakens Firefox's inherent sandboxing capabilities because they are restricted from using user-namespaces. It also seems that user-namespaces provide value with Firefox's sandboxing capacity. Also, given that subsequently capabilities are dropped, there should be reduced risk even if user-namespaces are in use.(?) ### Environment - Debian trixie - `6.12.73+deb13-amd64` - AppArmor enforced for `firejail` ### Checklist <!-- Note: Items are checked with an "x", like so: - [x] This is a checked item. --> - [X] I am using firejail [0.9.78 or later](https://github.com/netblue30/firejail/tree/master/SECURITY.md) - [X] I am using the full program path (e.g. `firejail /usr/bin/vlc` instead of `firejail vlc`; see `https://github.com/netblue30/firejail/issues/2877`) - [X] The issues is caused by firejail (i.e. running the program by path (e.g. `/usr/bin/vlc`) "fixes" it). - [X] I can reproduce the issue without custom modifications (e.g. globals.local). - [X] The program has a profile. (If not, request one in `https://github.com/netblue30/firejail/issues/1139`) - [X] The profile (and redirect profile if exists) hasn't already been fixed [upstream](https://github.com/netblue30/firejail/tree/master/etc). - [X] I have performed a short search for similar issues (to avoid opening a duplicate). - [X] I'm aware of `browser-allow-drm yes`/`browser-disable-u2f no` in `firejail.config` to allow DRM/U2F in browsers. - [X] I used `--profile=PROFILENAME` to set the right profile. (Only relevant for AppImages) ### Log N/A
Author
Owner

@cobratbq commented on GitHub (Feb 25, 2026):

Possible fix: add userns to beginning of firejail-default profile. This grants firejail access to user-namespaces which can then choose to delegate as profile/options ddecide.

profile firejail-default flags=(attach_disconnected, mediate_deleted) {
userns,

IIUC, adding userns to the AppArmor-profile for firejail is effectively the same as previous AppArmor without this addition, because it only recent got to being managed. It effectively allows user-namespaces thus deferring to firejail to determine whether to continue to allow it.

<!-- gh-comment-id:3956269199 --> @cobratbq commented on GitHub (Feb 25, 2026): Possible fix: add `userns` to beginning of `firejail-default` profile. This grants firejail access to user-namespaces which can then choose to delegate as profile/options ddecide. ``` profile firejail-default flags=(attach_disconnected, mediate_deleted) { userns, ``` IIUC, adding `userns` to the AppArmor-profile for firejail is effectively the same as previous AppArmor without this addition, because it only recent got to being managed. It effectively allows user-namespaces thus deferring to `firejail` to determine whether to continue to allow it.
Author
Owner

@kmk3 commented on GitHub (Feb 25, 2026):

Possible fix: add userns to beginning of firejail-default profile. This
grants firejail access to user-namespaces which can then choose to delegate
as profile/options ddecide.

profile firejail-default flags=(attach_disconnected, mediate_deleted) {
userns,

IIUC, adding userns to the AppArmor-profile for firejail is effectively the
same as previous AppArmor without this addition, because it only recent got
to being managed. It effectively allows user-namespaces thus deferring to
firejail to determine whether to continue to allow it.

Nice, since this makes the profile work the same as in AppArmor 3, sounds good
to me.

Would you like to open a PR?

Also, would that change remove the need for apparmor-replace in
firefox-common.profile (see #5475)?

Edit: I see now that this is a much older issue, so probably not.

<!-- gh-comment-id:3959379274 --> @kmk3 commented on GitHub (Feb 25, 2026): > Possible fix: add `userns` to beginning of `firejail-default` profile. This > grants firejail access to user-namespaces which can then choose to delegate > as profile/options ddecide. > > ``` > profile firejail-default flags=(attach_disconnected, mediate_deleted) { > userns, > ``` > > IIUC, adding `userns` to the AppArmor-profile for firejail is effectively the > same as previous AppArmor without this addition, because it only recent got > to being managed. It effectively allows user-namespaces thus deferring to > `firejail` to determine whether to continue to allow it. Nice, since this makes the profile work the same as in AppArmor 3, sounds good to me. Would you like to open a PR? Also, would that change remove the need for `apparmor-replace` in firefox-common.profile (see #5475)? Edit: I see now that this is a much older issue, so probably not.
Author
Owner

@kmk3 commented on GitHub (Feb 25, 2026):

(Feel free to ignore this until after the fix)

Since you're already looking into this, as a potential improvement, do you know
if it's possible to have an apparmor profile (such as "firejail-userns") with
just userns (plus whatever boilerplate is needed) and then conditionally
stack it (with aa_stack_onexec())?

For example, if restrict-namespaces is not used, we could just stack an
userns apparmor profile in src/firejail/sandbox.c.

Then a profile with restrict-namespaces would get both a firejail and
apparmor restriction on user namespaces and a profile without that can just use
them normally.

<!-- gh-comment-id:3959470372 --> @kmk3 commented on GitHub (Feb 25, 2026): (Feel free to ignore this until after the fix) Since you're already looking into this, as a potential improvement, do you know if it's possible to have an apparmor profile (such as "firejail-userns") with just `userns` (plus whatever boilerplate is needed) and then conditionally stack it (with `aa_stack_onexec()`)? For example, if `restrict-namespaces` is not used, we could just stack an userns apparmor profile in src/firejail/sandbox.c. Then a profile with `restrict-namespaces` would get both a firejail and apparmor restriction on user namespaces and a profile without that can just use them normally.
Author
Owner

@cobratbq commented on GitHub (Feb 25, 2026):

Possible fix: add userns to beginning of firejail-default profile. This
grants firejail access to user-namespaces which can then choose to delegate
as profile/options ddecide.

profile firejail-default flags=(attach_disconnected, mediate_deleted) {
userns,

IIUC, adding userns to the AppArmor-profile for firejail is effectively the
same as previous AppArmor without this addition, because it only recent got
to being managed. It effectively allows user-namespaces thus deferring to
firejail to determine whether to continue to allow it.

Nice, since this makes the profile work the same as in AppArmor 3, sounds good to me.

Assuming that this abi/4.0 indicates a "language" version, thus available keywords, then AppArmor 3 would likely reject the profile, but would do so already. (I'm guessing as to its meaning, so I'm not 100% sure.)

Would you like to open a PR?

I'll do that.

Also, would that change remove the need for apparmor-replace in firefox-common.profile (see #5475)?

Edit: I see now that this is a much older issue, so probably not.

I don't know exactly. I haven't looked into the reason for why apparmor-replace was necessary in the first place.

<!-- gh-comment-id:3961768082 --> @cobratbq commented on GitHub (Feb 25, 2026): > > Possible fix: add `userns` to beginning of `firejail-default` profile. This > > grants firejail access to user-namespaces which can then choose to delegate > > as profile/options ddecide. > > ``` > > profile firejail-default flags=(attach_disconnected, mediate_deleted) { > > userns, > > ``` > > > > IIUC, adding `userns` to the AppArmor-profile for firejail is effectively the > > same as previous AppArmor without this addition, because it only recent got > > to being managed. It effectively allows user-namespaces thus deferring to > > `firejail` to determine whether to continue to allow it. > > Nice, since this makes the profile work the same as in AppArmor 3, sounds good to me. Assuming that this `abi/4.0` indicates a "language" version, thus available keywords, then AppArmor 3 would likely reject the profile, but would do so already. (I'm guessing as to its meaning, so I'm not 100% sure.) > Would you like to open a PR? I'll do that. > Also, would that change remove the need for `apparmor-replace` in firefox-common.profile (see [#5475](https://github.com/netblue30/firejail/pull/5475))? > > Edit: I see now that this is a much older issue, so probably not. I don't know exactly. I haven't looked into the reason for why `apparmor-replace` was necessary in the first place.
Author
Owner

@cobratbq commented on GitHub (Feb 25, 2026):

(Feel free to ignore this until after the fix)

Since you're already looking into this, as a potential improvement, do you know if it's possible to have an apparmor profile (such as "firejail-userns") with just userns (plus whatever boilerplate is needed) and then conditionally stack it (with aa_stack_onexec())?

I don't think you should want to. Firejail is intended to manage capabilities, restrictions, etc. Do you not trust it to drop userns restrictions when --restrict-namespaces is (correctly) applied?

I wonder if the added complexity is even desirable.

For example, if restrict-namespaces is not used, we could just stack an userns apparmor profile in src/firejail/sandbox.c.

This is firejail protecting itself from itself, primarily. Don't you agree?

Then a profile with restrict-namespaces would get both a firejail and apparmor restriction on user namespaces and a profile without that can just use them normally.

They're effectively the same restrictions, but managed by a different program, isn't it? They're the same underlying capabilities or restrictions or syscalls.

<!-- gh-comment-id:3961787652 --> @cobratbq commented on GitHub (Feb 25, 2026): > (Feel free to ignore this until after the fix) > > Since you're already looking into this, as a potential improvement, do you know if it's possible to have an apparmor profile (such as "firejail-userns") with just `userns` (plus whatever boilerplate is needed) and then conditionally stack it (with `aa_stack_onexec()`)? I don't think you should want to. Firejail is intended to manage capabilities, restrictions, etc. Do you not trust it to drop `userns` restrictions when `--restrict-namespaces` is (correctly) applied? I wonder if the added complexity is even desirable. > For example, if `restrict-namespaces` is not used, we could just stack an userns apparmor profile in src/firejail/sandbox.c. This is `firejail` protecting itself from itself, primarily. Don't you agree? > Then a profile with `restrict-namespaces` would get both a firejail and apparmor restriction on user namespaces and a profile without that can just use them normally. They're effectively the same restrictions, but managed by a different program, isn't it? They're the same underlying capabilities or restrictions or syscalls.
Author
Owner

@kmk3 commented on GitHub (Feb 25, 2026):

(Feel free to ignore this until after the fix) Since you're already looking
into this, as a potential improvement, do you know if it's possible to have
an apparmor profile (such as "firejail-userns") with just userns (plus
whatever boilerplate is needed) and then conditionally stack it (with
aa_stack_onexec())?

I don't think you should want to. Firejail is intended to manage
capabilities, restrictions, etc. Do you not trust it to drop userns
restrictions when --restrict-namespaces is (correctly) applied?

I wonder if the added complexity is even desirable.

From looking at the code, I don't think it would be a notable increase in
complexity code-wise (assuming it works with apparmor 3.x).

For example, if restrict-namespaces is not used, we could just stack an
userns apparmor profile in src/firejail/sandbox.c.

This is firejail protecting itself from itself, primarily. Don't you agree?

AIUI the "firejail-default" apparmor profile applies to the sandboxed program,
not to firejail itself.

So it's more about defense-in-depth.

Assuming that firejail is less than perfect and that its attempt to restrict
user namespaces could fail (such as due to a new change causing a bug, etc),
then the user would still have the apparmor restriction.

Then a profile with restrict-namespaces would get both a firejail and
apparmor restriction on user namespaces and a profile without that can just
use them normally.

They're effectively the same restrictions, but managed by a different
program, isn't it? They're the same underlying capabilities or restrictions
or syscalls.

The user namespace restrictions in firejail and apparmor have the same intent,
but I don't think that their implementations are equivalent.

The one in firejail seems to be done through seccomp BPF (with fseccomp), which
is not as simple as calling a function or a path-based restriction (as is done
for some firejail commands).

Also, judging by the multiple CVEs related to unprivileged user namespaces and
the lengthy discussion in #6675, it seems like the extra assurance would be
welcomed.

Lastly, if the user believes that apparmor is redundant, they can just use
ignore apparmor and they would be unaffected by this either way.

<!-- gh-comment-id:3962172833 --> @kmk3 commented on GitHub (Feb 25, 2026): > > (Feel free to ignore this until after the fix) Since you're already looking > > into this, as a potential improvement, do you know if it's possible to have > > an apparmor profile (such as "firejail-userns") with just `userns` (plus > > whatever boilerplate is needed) and then conditionally stack it (with > > `aa_stack_onexec()`)? > > I don't think you should want to. Firejail is intended to manage > capabilities, restrictions, etc. Do you not trust it to drop `userns` > restrictions when `--restrict-namespaces` is (correctly) applied? > > I wonder if the added complexity is even desirable. From looking at the code, I don't think it would be a notable increase in complexity code-wise (assuming it works with apparmor 3.x). > > For example, if `restrict-namespaces` is not used, we could just stack an > > userns apparmor profile in src/firejail/sandbox.c. > > This is `firejail` protecting itself from itself, primarily. Don't you agree? AIUI the "firejail-default" apparmor profile applies to the sandboxed program, not to firejail itself. So it's more about defense-in-depth. Assuming that firejail is less than perfect and that its attempt to restrict user namespaces could fail (such as due to a new change causing a bug, etc), then the user would still have the apparmor restriction. > > Then a profile with `restrict-namespaces` would get both a firejail and > > apparmor restriction on user namespaces and a profile without that can just > > use them normally. > > They're effectively the same restrictions, but managed by a different > program, isn't it? They're the same underlying capabilities or restrictions > or syscalls. The user namespace restrictions in firejail and apparmor have the same intent, but I don't think that their implementations are equivalent. The one in firejail seems to be done through seccomp BPF (with fseccomp), which is not as simple as calling a function or a path-based restriction (as is done for some firejail commands). Also, judging by the multiple CVEs related to unprivileged user namespaces and the lengthy discussion in #6675, it seems like the extra assurance would be welcomed. Lastly, if the user believes that apparmor is redundant, they can just use `ignore apparmor` and they would be unaffected by this either way.
Author
Owner

@cobratbq commented on GitHub (Feb 28, 2026):

From looking at the code, I don't think it would be a notable increase in complexity code-wise (assuming it works with apparmor 3.x).

I am not familiar enough with the code, and haven't looked into it, so I'll go by your feedback.

This is firejail protecting itself from itself, primarily. Don't you agree?

AIUI the "firejail-default" apparmor profile applies to the sandboxed program, not to firejail itself.

Hmm... actually, you are correct. I am mistaken and also my description. Effectively, it matters little, but indeed firejail itself is not constrained using /etc/apparmor.d/firejail-default and I should've realized because I looked into this and didn't see the pattern for /usr/bin/firejail.

So it's more about defense-in-depth.

Yes. Clear.

Assuming that firejail is less than perfect and that its attempt to restrict user namespaces could fail (such as due to a new change causing a bug, etc), then the user would still have the apparmor restriction.

But conversely, if the apparmor-profile firejail-default is applied without userns, then firejail can no longer decide to allow user-namespaces. Sure, then choosing an appropriate profile makes sense.

But, then my question is: What about blocking access to network protocols? Those are also in AppArmor 4.0 (possibly earlier, not sure). Would you also make separate profiles for those for the same reason of defense-in-depth? I.e. do you have a rationale for where you draw the line?

Then a profile with restrict-namespaces would get both a firejail and
apparmor restriction on user namespaces and a profile without that can just
use them normally.

They're effectively the same restrictions, but managed by a different
program, isn't it? They're the same underlying capabilities or restrictions
or syscalls.

The user namespace restrictions in firejail and apparmor have the same intent, but I don't think that their implementations are equivalent.

Likely, AppArmor has more direct influence, given that it is a kernel security module, but then so does the capabilities framework. Even then, it could still function for defense-in-depth against edge-cases.

The one in firejail seems to be done through seccomp BPF (with fseccomp), which is not as simple as calling a function or a path-based restriction (as is done for some firejail commands).

How about the capabilities? Because, to my knowledge, those are a registered security module in /sys/kernel/security/lsm, so it would have more direct influence.

Also, judging by the multiple CVEs related to unprivileged user namespaces and the lengthy discussion in #6675, it seems like the extra assurance would be welcomed.

That is true. However, I've read about needing CAP_SYS_ADMIN in user-namespaces, which is more restricted/crippled, and then break out to then acquire un-neutered CAP_SYS_ADMIN privileges in the system namespace (or however that instance is called). Similarly, the recent user-namespace vulnerabilities in Ubuntu, IIUC, required "hitch-hiking" on liberal AppArmor-profiles such as of busybox using aa-exec or something alike. I can bring little expertise apart from being somewhat informed from news articles.

Lastly, if the user believes that apparmor is redundant, they can just use ignore apparmor and they would be unaffected by this either way.

Yes, this is true. However, e.g. web browsers use it to apply more granular compartmentalization (I think) and you remove that ability entirely, which may mean that you provide smaller surface area for vulnerabilities to break out of the isolated environment as a whole, but may increase vulnerability for various compartmentalized regions inside the program. (Again, in my limited understanding.)

I was thinking about the case for development environments with LSPs, processes and agents. Those run quite a few foreign processes, so compartmentalization may be (or become) more important, which is where user-namespaces would help. Otherwise they would need to resort to SUID-executables to set up sandboxed (internal) (sub-)processes.

edit the last response, i.e. directly preceding this note, was written under the mistaken assumption that firejail would invariably be restricted by firejail-default apparmor-profile. This is an incorrect assumption on my part. (https://github.com/netblue30/firejail/pull/7080#issuecomment-3962047923)

<!-- gh-comment-id:3976132538 --> @cobratbq commented on GitHub (Feb 28, 2026): > From looking at the code, I don't think it would be a notable increase in complexity code-wise (assuming it works with apparmor 3.x). I am not familiar enough with the code, and haven't looked into it, so I'll go by your feedback. > > This is `firejail` protecting itself from itself, primarily. Don't you agree? > > AIUI the "firejail-default" apparmor profile applies to the sandboxed program, not to firejail itself. Hmm... actually, you are correct. I am mistaken and also my description. Effectively, it matters little, but indeed `firejail` itself is not constrained using `/etc/apparmor.d/firejail-default` and I should've realized because I looked into this and didn't see the pattern for `/usr/bin/firejail`. > So it's more about defense-in-depth. Yes. Clear. > Assuming that firejail is less than perfect and that its attempt to restrict user namespaces could fail (such as due to a new change causing a bug, etc), then the user would still have the apparmor restriction. But conversely, if the apparmor-profile `firejail-default` is applied without `userns`, then firejail can no longer decide to allow user-namespaces. Sure, then choosing an appropriate profile makes sense. But, then my question is: What about blocking access to network protocols? Those are also in AppArmor 4.0 (possibly earlier, not sure). Would you also make separate profiles for those for the same reason of defense-in-depth? I.e. do you have a rationale for where you draw the line? > > > Then a profile with `restrict-namespaces` would get both a firejail and > > > apparmor restriction on user namespaces and a profile without that can just > > > use them normally. > > > > > > They're effectively the same restrictions, but managed by a different > > program, isn't it? They're the same underlying capabilities or restrictions > > or syscalls. > > The user namespace restrictions in firejail and apparmor have the same intent, but I don't think that their implementations are equivalent. Likely, AppArmor has more direct influence, given that it is a kernel security module, but then so does the capabilities framework. Even then, it could still function for defense-in-depth against edge-cases. > The one in firejail seems to be done through seccomp BPF (with fseccomp), which is not as simple as calling a function or a path-based restriction (as is done for some firejail commands). How about the capabilities? Because, to my knowledge, those are a registered security module in `/sys/kernel/security/lsm`, so it would have more direct influence. > Also, judging by the multiple CVEs related to unprivileged user namespaces and the lengthy discussion in [#6675](https://github.com/netblue30/firejail/issues/6675), it seems like the extra assurance would be welcomed. That is true. However, I've read about needing `CAP_SYS_ADMIN` in user-namespaces, which is more restricted/crippled, and then break out to then acquire un-neutered `CAP_SYS_ADMIN` privileges in the system namespace (or however that instance is called). Similarly, the recent user-namespace vulnerabilities in Ubuntu, IIUC, required "hitch-hiking" on liberal AppArmor-profiles such as of `busybox` using `aa-exec` or something alike. I can bring little expertise apart from being somewhat informed from news articles. > Lastly, if the user believes that apparmor is redundant, they can just use `ignore apparmor` and they would be unaffected by this either way. Yes, this is true. However, e.g. web browsers use it to apply more granular compartmentalization (I think) and you remove that ability entirely, which may mean that you provide smaller surface area for vulnerabilities to break out of the isolated environment as a whole, but may increase vulnerability for various compartmentalized regions inside the program. (Again, in my limited understanding.) I was thinking about the case for development environments with LSPs, processes and agents. Those run quite a few foreign processes, so compartmentalization may be (or become) more important, which is where user-namespaces would help. Otherwise they would need to resort to SUID-executables to set up sandboxed (internal) (sub-)processes. __edit__ the last response, i.e. directly preceding this note, was written under the mistaken assumption that firejail would invariably be restricted by `firejail-default` apparmor-profile. This is an incorrect assumption on my part. (<https://github.com/netblue30/firejail/pull/7080#issuecomment-3962047923>)
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#3479
No description provided.