[GH-ISSUE #3862] Paths in app profiles with ^ and ! wildcards in them are not expanded #2431

Open
opened 2026-05-05 09:06:27 -06:00 by gitea-mirror · 9 comments
Owner

Originally created by @Snugface on GitHub (Jan 1, 2021).
Original GitHub issue: https://github.com/netblue30/firejail/issues/3862

Bug and expected behavior

  • Firejail can not expand paths with wildcards ^ and ! in them when reading profile files.
  • Expected to be able to expand wildcards such as [^.]*/ and *!(.)/

Reproduce
Steps to reproduce the behavior:

  1. Make a local FF profile:
cp /etc/firejail/firefox.profile ~/.config/firejail/
cp /etc/firejail/firefox-common.profile ~/.config/firejail/
  1. Create test directory structure & files:
mkdir -p ~/parent_dir/child_dir{1..10}
touch ~/parent_dir/file{1..10}
  1. Add additional lines to ~/.config/firejail/firefox-common.profile after the line include whitelist-var-common.inc:
whitelist ${HOME}/parent_dir
blacklist ${HOME}/parent_dir/[^.]*/
blacklist ${HOME}/parent_dir/.[^.]*/
  1. Run firejail firefox

Environment

  • Artix Linux(Arch Linux with OpenRC init system) running a hardened kernel(package linux-hardened), last updated ~10 days ago
  • Firejail version 0.9.64
  • AppArmor is also running on the system; however, to my knowledge, firefox profile is inactive(though I could be wrong about this). I myself have not activated it; and it is not shown in the output of # aa-status anywhere

Additional context

  • I wanted to blacklist every child directory of ~/parent_dir, and whitelist the parent_dir itself and all files in it.
    Glob pattern blacklist ${HOME}/parent_dir/*/ was used. This also blacklisted ${HOME}/parent_dir/.. which is the $HOME itself. Which broke firefox and it failed to execute.
  • Attempted a workaround with [^.]*/ and .[^.]*/ wildcards instead of */.
    The two glob patterns list all regular and . directories except /.. if used directly from a bash shell(such as with echo [^.]*/) However, upon starting firefox I get:
    Error: "${HOME}/parent_dir/[^.]*/" is an invalid filename: rejected character: "^"
  • I don't really care whether ^ and ! work - it's just important for me to be able to use wildcards to blacklist/whitelist all child directories, but not all files, in a specific parent directory. So if you know a specific recipe for this - please, share it. I'd be glad to tip you some $10-20 if there will be a workaround.

Checklist

  • The upstream profile (and redirect profile if exists) have no changes fixing it.
  • The program has a profile.
  • A short search for duplicates was performed.
  • If it is a AppImage, --profile=PROFILENAME is used to set the right profile.
  • Used LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 PROGRAM to get english error-messages.
  • I'm aware of browser-allow-drm yes/browser-disable-u2f no in firejail.config to allow DRM/U2F in browsers.
debug output
Autoselecting /bin/bash as shell
Building quoted command line: 'firefox' 
Command name #firefox#
Found firefox.profile profile in /home/eviscerator/.config/firejail directory
Reading profile /home/eviscerator/.config/firejail/firefox.profile
Found whitelist-usr-share-common.inc profile in /etc/firejail directory
Reading profile /etc/firejail/whitelist-usr-share-common.inc
Found firefox-common.profile profile in /home/eviscerator/.config/firejail directory
Reading profile /home/eviscerator/.config/firejail/firefox-common.profile
Found disable-common.inc profile in /etc/firejail directory
Reading profile /etc/firejail/disable-common.inc
Found disable-devel.inc profile in /etc/firejail directory
Reading profile /etc/firejail/disable-devel.inc
Found disable-exec.inc profile in /etc/firejail directory
Reading profile /etc/firejail/disable-exec.inc
Found disable-interpreters.inc profile in /etc/firejail directory
Reading profile /etc/firejail/disable-interpreters.inc
Found disable-programs.inc profile in /etc/firejail directory
Reading profile /etc/firejail/disable-programs.inc
Found whitelist-common.inc profile in /etc/firejail directory
Reading profile /etc/firejail/whitelist-common.inc
Found whitelist-var-common.inc profile in /etc/firejail directory
Reading profile /etc/firejail/whitelist-var-common.inc
Error: "${HOME}/parent_dir/[^.]*/" is an invalid filename: rejected character: "^"
Originally created by @Snugface on GitHub (Jan 1, 2021). Original GitHub issue: https://github.com/netblue30/firejail/issues/3862 **Bug and expected behavior** - Firejail can not expand paths with wildcards `^` and `!` in them when reading profile files. - Expected to be able to expand wildcards such as `[^.]*/` and `*!(.)/` **Reproduce** Steps to reproduce the behavior: 1. Make a local FF profile: ``` cp /etc/firejail/firefox.profile ~/.config/firejail/ cp /etc/firejail/firefox-common.profile ~/.config/firejail/ ``` 2. Create test directory structure & files: ``` mkdir -p ~/parent_dir/child_dir{1..10} touch ~/parent_dir/file{1..10} ``` 4. Add additional lines to `~/.config/firejail/firefox-common.profile` after the line `include whitelist-var-common.inc`: ``` whitelist ${HOME}/parent_dir blacklist ${HOME}/parent_dir/[^.]*/ blacklist ${HOME}/parent_dir/.[^.]*/ ``` 5. Run `firejail firefox` **Environment** - Artix Linux(Arch Linux with OpenRC init system) running a hardened kernel(package `linux-hardened`), last updated ~10 days ago - Firejail version 0.9.64 - AppArmor is also running on the system; however, to my knowledge, firefox profile is inactive(though I could be wrong about this). I myself have not activated it; and it is not shown in the output of `# aa-status` anywhere **Additional context** - I wanted to **blacklist** _every child directory_ of `~/parent_dir`, and **whitelist** the `parent_dir` _itself_ and _all files_ in it. Glob pattern `blacklist ${HOME}/parent_dir/*/` was used. This also **blacklisted** `${HOME}/parent_dir/..` which is the `$HOME` itself. Which broke firefox and it failed to execute. - Attempted a workaround with `[^.]*/` and `.[^.]*/` wildcards instead of `*/`. The two glob patterns list all regular and `.` directories except `/..` if used directly from a bash shell(such as with `echo [^.]*/`) However, upon starting firefox I get: `Error: "${HOME}/parent_dir/[^.]*/" is an invalid filename: rejected character: "^"` - I don't really care whether `^` and `!` work - it's just important for me to be able to use wildcards to blacklist/whitelist all child directories, but not all files, in a specific parent directory. So if you know a specific recipe for this - please, share it. I'd be glad to tip you some $10-20 if there will be a workaround. **Checklist** - [ ] The upstream profile (and redirect profile if exists) have no changes fixing it. - [x] The program has a profile. - [x] A short search for duplicates was performed. - [x] If it is a AppImage, `--profile=PROFILENAME` is used to set the right profile. - [x] Used `LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 PROGRAM` to get english error-messages. - [x] I'm aware of `browser-allow-drm yes`/`browser-disable-u2f no` in `firejail.config` to allow DRM/U2F in browsers. <details><summary> debug output </summary> ``` Autoselecting /bin/bash as shell Building quoted command line: 'firefox' Command name #firefox# Found firefox.profile profile in /home/eviscerator/.config/firejail directory Reading profile /home/eviscerator/.config/firejail/firefox.profile Found whitelist-usr-share-common.inc profile in /etc/firejail directory Reading profile /etc/firejail/whitelist-usr-share-common.inc Found firefox-common.profile profile in /home/eviscerator/.config/firejail directory Reading profile /home/eviscerator/.config/firejail/firefox-common.profile Found disable-common.inc profile in /etc/firejail directory Reading profile /etc/firejail/disable-common.inc Found disable-devel.inc profile in /etc/firejail directory Reading profile /etc/firejail/disable-devel.inc Found disable-exec.inc profile in /etc/firejail directory Reading profile /etc/firejail/disable-exec.inc Found disable-interpreters.inc profile in /etc/firejail directory Reading profile /etc/firejail/disable-interpreters.inc Found disable-programs.inc profile in /etc/firejail directory Reading profile /etc/firejail/disable-programs.inc Found whitelist-common.inc profile in /etc/firejail directory Reading profile /etc/firejail/whitelist-common.inc Found whitelist-var-common.inc profile in /etc/firejail directory Reading profile /etc/firejail/whitelist-var-common.inc Error: "${HOME}/parent_dir/[^.]*/" is an invalid filename: rejected character: "^" ``` </details>
Author
Owner

@rusty-snake commented on GitHub (Mar 8, 2021):

man 7 glob: You can do [!.]* however Error: "${HOME}/parent_dir/.[!.]*/" is an invalid filename: rejected character: "!".

<!-- gh-comment-id:793015133 --> @rusty-snake commented on GitHub (Mar 8, 2021): `man 7 glob`: You can do `[!.]*` however `Error: "${HOME}/parent_dir/.[!.]*/" is an invalid filename: rejected character: "!"`.
Author
Owner

@rusty-snake commented on GitHub (May 12, 2021):

For me this raises two questions:

  1. Can we allow ! (after [) in paths?
  2. Do we want to reimplement path handling using e.g. pcre?
<!-- gh-comment-id:840109404 --> @rusty-snake commented on GitHub (May 12, 2021): For me this raises two questions: 1. Can we allow `!` (after `[`) in paths? 2. Do we want to reimplement path handling using e.g. pcre?
Author
Owner

@kmk3 commented on GitHub (May 13, 2021):

@Snugface commented on Jan 1:

Additional context

  • I wanted to blacklist every child directory of ~/parent_dir, and
    whitelist the parent_dir itself and all files in it. Glob
    pattern blacklist ${HOME}/parent_dir/*/ was used. This also
    blacklisted ${HOME}/parent_dir/.. which is the $HOME itself. Which
    broke firefox and it failed to execute.

  • Attempted a workaround with [^.]*/ and .[^.]*/ wildcards instead of
    */. The two glob patterns list all regular and . directories except
    /.. if used directly from a bash shell(such as with echo [^.]*/)
    However, upon starting firefox I get: Error: "${HOME}/parent_dir/[^.]*/" is an invalid filename: rejected character: "^"

  • I don't really care whether ^ and ! work - it's just important for me
    to be able to use wildcards to blacklist/whitelist all child directories,
    but not all files, in a specific parent directory. So if you know a
    specific recipe for this - please, share it. I'd be glad to tip you some
    $10-20 if there will be a workaround.

I think it would be simpler to just fix globbing to ignore /..$ and /.$.

@rusty-snake commented 10 hours ago:

For me this raises two questions:

  1. Can we allow ! (after [) in paths?

  2. Do we want to reimplement path handling using e.g. pcre?

PCRE is quite large/complex; POSIX ERE already supports [^.]:

If you really want to use an external implementation, I'd suggest using a
smaller one. Examples:

This one seems to be more common (it's used by jq and PHP), but it's on the
larger side:

And there's a fork that's used by Ruby, though on Arch it only exists in the
AUR:

<!-- gh-comment-id:840374729 --> @kmk3 commented on GitHub (May 13, 2021): @Snugface commented on Jan 1: > **Additional context** > > * I wanted to **blacklist** _every child directory_ of `~/parent_dir`, and > **whitelist** the `parent_dir` _itself_ and _all files_ in it. Glob > pattern `blacklist ${HOME}/parent_dir/*/` was used. This also > **blacklisted** `${HOME}/parent_dir/..` which is the `$HOME` itself. Which > broke firefox and it failed to execute. > > * Attempted a workaround with `[^.]*/` and `.[^.]*/` wildcards instead of > `*/`. The two glob patterns list all regular and `.` directories except > `/..` if used directly from a bash shell(such as with `echo [^.]*/`) > However, upon starting firefox I get: `Error: "${HOME}/parent_dir/[^.]*/" > is an invalid filename: rejected character: "^"` > > * I don't really care whether `^` and `!` work - it's just important for me > to be able to use wildcards to blacklist/whitelist all child directories, > but not all files, in a specific parent directory. So if you know a > specific recipe for this - please, share it. I'd be glad to tip you some > $10-20 if there will be a workaround. I think it would be simpler to just fix globbing to ignore `/..$` and `/.$`. @rusty-snake commented 10 hours ago: > For me this raises two questions: > > 1. Can we allow `!` (after `[`) in paths? > > 2. Do we want to reimplement path handling using e.g. pcre? PCRE is quite large/complex; POSIX ERE already supports `[^.]`: * [POSIX.1‐2017, Chapter 9, Regular Expressions][1] * [regcomp(3p)][2] If you really want to use an external implementation, I'd suggest using a smaller one. Examples: * <https://github.com/kokke/tiny-regex-c> * <https://github.com/mattbucknall/subreg> (Note: The tests require CMake) This one seems to be more common (it's used by `jq` and PHP), but it's on the larger side: * <https://github.com/kkos/oniguruma> And there's a fork that's used by Ruby, though on Arch it only exists in the AUR: * <https://github.com/k-takata/Onigmo> [1]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html [2]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/regcomp.html
Author
Owner

@rusty-snake commented on GitHub (May 13, 2021):

PCRE is quite large/complex

You're right, however for me:

$ ldd /usr/bin/firejail
	linux-vdso.so.1 (0x00007ffdb2f40000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007c1c43488000)
	libc.so.6 => /lib64/libc.so.6 (0x00007c1c432b9000)
	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007c1c43222000)  <---
	libdl.so.2 => /lib64/libdl.so.2 (0x00007c1c4321b000)
	/lib64/ld-linux-x86-64.so.2 (0x00007c1c4362d000)
<!-- gh-comment-id:840379377 --> @rusty-snake commented on GitHub (May 13, 2021): > PCRE is quite large/complex You're right, however for me: ``` $ ldd /usr/bin/firejail linux-vdso.so.1 (0x00007ffdb2f40000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007c1c43488000) libc.so.6 => /lib64/libc.so.6 (0x00007c1c432b9000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007c1c43222000) <--- libdl.so.2 => /lib64/libdl.so.2 (0x00007c1c4321b000) /lib64/ld-linux-x86-64.so.2 (0x00007c1c4362d000) ```
Author
Owner

@kmk3 commented on GitHub (May 13, 2021):

PCRE is quite large/complex

You're right, however for me:

$ ldd /usr/bin/firejail
	linux-vdso.so.1 (0x00007ffdb2f40000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007c1c43488000)
	libc.so.6 => /lib64/libc.so.6 (0x00007c1c432b9000)
	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007c1c43222000)  <---
	libdl.so.2 => /lib64/libdl.so.2 (0x00007c1c4321b000)
	/lib64/ld-linux-x86-64.so.2 (0x00007c1c4362d000)
$ ldd /usr/bin/firejail
        linux-vdso.so.1 (0x00007ffd92b8c000)
        libapparmor.so.1 => /usr/lib/libapparmor.so.1 (0x00007fee1f8b0000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007fee1f6e0000)
        libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fee1f6b8000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fee1fa70000)
<!-- gh-comment-id:840381101 --> @kmk3 commented on GitHub (May 13, 2021): > > PCRE is quite large/complex > > You're right, however for me: > > ``` > $ ldd /usr/bin/firejail > linux-vdso.so.1 (0x00007ffdb2f40000) > libselinux.so.1 => /lib64/libselinux.so.1 (0x00007c1c43488000) > libc.so.6 => /lib64/libc.so.6 (0x00007c1c432b9000) > libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007c1c43222000) <--- > libdl.so.2 => /lib64/libdl.so.2 (0x00007c1c4321b000) > /lib64/ld-linux-x86-64.so.2 (0x00007c1c4362d000) > ``` ```console $ ldd /usr/bin/firejail linux-vdso.so.1 (0x00007ffd92b8c000) libapparmor.so.1 => /usr/lib/libapparmor.so.1 (0x00007fee1f8b0000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fee1f6e0000) libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fee1f6b8000) /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fee1fa70000) ```
Author
Owner

@rusty-snake commented on GitHub (May 13, 2021):

./configure without --enable-selinux:

$ ldd /usr/bin/firejail
	linux-vdso.so.1 (0x00007fffdd140000)
	libc.so.6 => /lib64/libc.so.6 (0x000077878c5b9000)
	/lib64/ld-linux-x86-64.so.2 (0x000077878c900000)

./configure with --enable-selinux:

$ ldd /usr/bin/firejail
	linux-vdso.so.1 (0x00007fffd43e9000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x000071786a3f7000)
	libc.so.6 => /lib64/libc.so.6 (0x000071786a228000)
	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x000071786a191000)
	libdl.so.2 => /lib64/libdl.so.2 (0x000071786a18a000)
	/lib64/ld-linux-x86-64.so.2 (0x000071786a59c000)
<!-- gh-comment-id:840384344 --> @rusty-snake commented on GitHub (May 13, 2021): `./configure` without `--enable-selinux`: ``` $ ldd /usr/bin/firejail linux-vdso.so.1 (0x00007fffdd140000) libc.so.6 => /lib64/libc.so.6 (0x000077878c5b9000) /lib64/ld-linux-x86-64.so.2 (0x000077878c900000) ``` `./configure` with `--enable-selinux`: ``` $ ldd /usr/bin/firejail linux-vdso.so.1 (0x00007fffd43e9000) libselinux.so.1 => /lib64/libselinux.so.1 (0x000071786a3f7000) libc.so.6 => /lib64/libc.so.6 (0x000071786a228000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x000071786a191000) libdl.so.2 => /lib64/libdl.so.2 (0x000071786a18a000) /lib64/ld-linux-x86-64.so.2 (0x000071786a59c000) ```
Author
Owner

@kmk3 commented on GitHub (May 13, 2021):

./configure without --enable-selinux:

$ ldd /usr/bin/firejail
	linux-vdso.so.1 (0x00007fffdd140000)
	libc.so.6 => /lib64/libc.so.6 (0x000077878c5b9000)
	/lib64/ld-linux-x86-64.so.2 (0x000077878c900000)

./configure with --enable-selinux:

$ ldd /usr/bin/firejail
	linux-vdso.so.1 (0x00007fffd43e9000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x000071786a3f7000)
	libc.so.6 => /lib64/libc.so.6 (0x000071786a228000)
	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x000071786a191000)
	libdl.so.2 => /lib64/libdl.so.2 (0x000071786a18a000)
	/lib64/ld-linux-x86-64.so.2 (0x000071786a59c000)

I see, it's a dependency of SELinux, but I don't really get what exactly is
your point.

<!-- gh-comment-id:840386270 --> @kmk3 commented on GitHub (May 13, 2021): > `./configure` without `--enable-selinux`: > > ``` > $ ldd /usr/bin/firejail > linux-vdso.so.1 (0x00007fffdd140000) > libc.so.6 => /lib64/libc.so.6 (0x000077878c5b9000) > /lib64/ld-linux-x86-64.so.2 (0x000077878c900000) > ``` > > `./configure` with `--enable-selinux`: > > ``` > $ ldd /usr/bin/firejail > linux-vdso.so.1 (0x00007fffd43e9000) > libselinux.so.1 => /lib64/libselinux.so.1 (0x000071786a3f7000) > libc.so.6 => /lib64/libc.so.6 (0x000071786a228000) > libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x000071786a191000) > libdl.so.2 => /lib64/libdl.so.2 (0x000071786a18a000) > /lib64/ld-linux-x86-64.so.2 (0x000071786a59c000) > ``` I see, it's a dependency of SELinux, but I don't really get what exactly is your point.
Author
Owner

@rusty-snake commented on GitHub (May 13, 2021):

Just to clear what causes the different ldd outputs.I didn't know this before.

<!-- gh-comment-id:840387355 --> @rusty-snake commented on GitHub (May 13, 2021): Just to clear what causes the different `ldd` outputs.I didn't know this before.
Author
Owner

@kmk3 commented on GitHub (May 13, 2021):

Just to clear what causes the different ldd outputs.I didn't know this
before.

Ah alright; I thought that you were arguing in favor of using PCRE directly.

<!-- gh-comment-id:840390270 --> @kmk3 commented on GitHub (May 13, 2021): > Just to clear what causes the different `ldd` outputs.I didn't know this > before. Ah alright; I thought that you were arguing in favor of using PCRE directly.
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#2431
No description provided.