CVE-2022-21682 (published 2022-01-13T21:15Z)

Flatpak is a Linux application sandboxing and distribution framework. A path traversal vulnerability affects versions of Flatpak prior to 1.12.3 and 1.10.6. flatpak-builder applies `finish-args` last in the build. At this point the build directory will have the full access that is specified in the manifest, so running `flatpak build` against it will gain those permissions. Normally this will not be done, so this is not problem. However, if `--mirror-screenshots-url` is specified, then flatpak-builder will launch `flatpak build --nofilesystem=host appstream-utils mirror-screenshots` after finalization, which can lead to issues even with the `--nofilesystem=host` protection. In normal use, the only issue is that these empty directories can be created wherever the user has write permissions. However, a malicious application could replace the `appstream-util` binary and potentially do something more hostile. This has been resolved in Flatpak 1.12.3 and 1.10.6 by changing the behaviour of `--nofilesystem=home` and `--nofilesystem=host`.

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:N/I:P/A:N)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/flatpak/flatpak
commit_details: repo_url: https://github.com/flatpak/flatpak
author: Alexander Larsson
author_date: 2022-01-10 13:29:44+01:00
msg: manpages: Document the new details of --nofilesystem behaviour.
repository: repo_url: https://github.com/flatpak/flatpak
repo_name: flatpak/flatpak
description: Linux application sandboxing and distribution framework
repo_language: C
owner: flatpak
file_changes: filename: flatpak-build-finish.xml
change_type: ModificationType.MODIFY
diff: @@ -258,6 +258,13 @@
                     xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos,
                     an absolute path, or a homedir-relative path like ~/dir.
                     This option can be used multiple times.
+                </para><para>
+                    In general, "--nofilesystem=PATH" will remove access to a specific path if exactly that path
+                    was previously granted. However, as a special case, "--nofilesystem=home"  will remove access to all
+                    previously granted locations inside the homedir as well, such as "home/some-dir", or "xdg-download",
+                    and "--nofilesystem=host" will remove access to all previously granted locations.
+                    Note: absolute paths that happen to be inside the current users home directory are not considered for
+                    this special case.
                 </para></listitem>
             </varlistentry>
 

programming_language: Perl
filename: flatpak-build.xml
change_type: ModificationType.MODIFY
diff: @@ -247,6 +247,13 @@
                     xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos,
                     an absolute path, or a homedir-relative path like ~/dir.
                     This option can be used multiple times.
+                </para><para>
+                    In general, "--nofilesystem=PATH" will remove access to a specific path if exactly that path
+                    was previously granted. However, as a special case, "--nofilesystem=home" will remove access to all
+                    previously granted locations inside the homedir as well, such as "home/some-dir", or "xdg-download",
+                    and "--nofilesystem=host" will remove access to all previously granted locations.
+                    Note: absolute paths that happen to be inside the current users home directory are not considered for
+                    this special case.
                 </para></listitem>
             </varlistentry>
 

programming_language: HTML
filename: flatpak-override.xml
change_type: ModificationType.MODIFY
diff: @@ -230,6 +230,13 @@
                     xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos,
                     an absolute path, or a homedir-relative path like ~/dir.
                     This option can be used multiple times.
+                </para><para>
+                    In general, "--nofilesystem=PATH" will remove access to a specific path if exactly that path
+                    was previously granted. However, as a special case, "--nofilesystem=home" will remove access to all
+                    previously granted locations inside the homedir as well, such as "home/some-dir", or "xdg-download",
+                    and "--nofilesystem=host" will remove access to all previously granted locations.
+                    Note: absolute paths that happen to be inside the current users home directory are not considered for
+                    this special case.
                 </para></listitem>
             </varlistentry>
 

programming_language: HTML
filename: flatpak-run.xml
change_type: ModificationType.MODIFY
diff: @@ -381,7 +381,15 @@
                     xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos,
                     an absolute path, or a homedir-relative path like ~/dir.
                     This option can be used multiple times.
+                </para><para>
+                    In general, "--nofilesystem=PATH" will remove access to a specific path if exactly that path
+                    was previously granted. However, as a special case, "--nofilesystem=home" will remove access to all
+                    previously granted locations inside the homedir as well, such as "home/some-dir", or "xdg-download",
+                    and "--nofilesystem=host" will remove access to all previously granted locations.
+                    Note: absolute paths that happen to be inside the current users home directory are not considered for
+                    this special case.
                 </para></listitem>
+
             </varlistentry>
 
             <varlistentry>

programming_language: HTML
repo_url: https://github.com/flatpak/flatpak
commit_details: repo_url: https://github.com/flatpak/flatpak
author: Alexander Larsson
author_date: 2021-10-19 11:48:00+02:00
msg: Make --nofilesystem=host/home remove access to subdirs of those

Previously --nofilesystem=host only removed specifically access to the
`host` permissions, and not necessarily other filesystems (like `home`
or `/some/path`). This isn't very useful to limit access because you
don't know what other filesystems the app may have access too.

We change this to mean that `--nofilesystem=host` removes *all* filesystem
access from the parent layer, and `--nofilesystem=home` removes all
file access to the homedir and paths inside it.

The available layers are, in order:

 * app permissions
 * overrides
 * commandline args

This allows you to start from scratch with the filesystem permissions
in the overrides or the commandline. This is a small change in
behaviour, but not a lot of things use --nofilesystem, and the ones
that do probably expects this behaviour.
repository: repo_url: https://github.com/flatpak/flatpak
repo_name: flatpak/flatpak
description: Linux application sandboxing and distribution framework
repo_language: C
owner: flatpak
file_changes: filename: flatpak-context.c
change_type: ModificationType.MODIFY
diff: @@ -852,6 +852,31 @@ flatpak_context_parse_filesystem (const char             *filesystem_and_mode,
   return FALSE;
 }
 
+/* Note: This only works with valid keys, i.e. they passed flatpak_context_parse_filesystem */
+static gboolean
+flatpak_filesystem_key_in_home (const char *filesystem)
+{
+  /* "home" is definitely in home */
+  if (strcmp (filesystem, "home") == 0)
+    return TRUE;
+
+  /* All the other special fs:es are non-home.
+   * Note: This considers absolute paths that are in the homedir as non-home.
+   */
+  if (g_strv_contains (flatpak_context_special_filesystems, filesystem) ||
+      g_str_has_prefix (filesystem, "/"))
+    return FALSE;
+
+  /* Files in xdg-run are not in home */
+  if (g_str_has_prefix (filesystem, "xdg-run"))
+    return FALSE;
+
+  /* All remaining keys (~/, xdg-data, etc) are considered in home,
+   * Note: technically $XDG_HOME_DATA could point outside the homedir, but we ignore that.
+   */
+  return TRUE;
+}
+
 static void
 flatpak_context_take_filesystem (FlatpakContext        *context,
                                  char                  *fs,
@@ -866,6 +891,8 @@ flatpak_context_merge (FlatpakContext *context,
 {
   GHashTableIter iter;
   gpointer key, value;
+  gboolean no_home = FALSE;
+  gboolean no_host = FALSE;
 
   context->shares &= ~other->shares_valid;
   context->shares |= other->shares;
@@ -888,6 +915,41 @@ flatpak_context_merge (FlatpakContext *context,
   while (g_hash_table_iter_next (&iter, &key, &value))
     g_hash_table_insert (context->persistent, g_strdup (key), value);
 
+  /* We first handle all negative home and host as they override other
+     keys than themselves from the parent */
+  if (g_hash_table_lookup_extended (other->filesystems,
+                                    "host",
+                                    NULL, &value))
+    {
+      FlatpakFilesystemMode host_mode = GPOINTER_TO_INT (value);
+      if (host_mode == FLATPAK_FILESYSTEM_MODE_NONE)
+        no_host = TRUE;
+    }
+
+  if (g_hash_table_lookup_extended (other->filesystems,
+                                    "home",
+                                    NULL, &value))
+    {
+      FlatpakFilesystemMode home_mode = GPOINTER_TO_INT (value);
+      if (home_mode == FLATPAK_FILESYSTEM_MODE_NONE)
+        no_home = TRUE;
+    }
+
+  if (no_host)
+    {
+      g_hash_table_remove_all (context->filesystems);
+    }
+  else if (no_home)
+    {
+      g_hash_table_iter_init (&iter, context->filesystems);
+      while (g_hash_table_iter_next (&iter, &key, &value))
+        {
+          if (flatpak_filesystem_key_in_home ((const char *)key))
+            g_hash_table_iter_remove (&iter);
+        }
+    }
+
+  /* Then set the new ones, which includes propagating the nohost and nohome ones. */
   g_hash_table_iter_init (&iter, other->filesystems);
   while (g_hash_table_iter_next (&iter, &key, &value))
     g_hash_table_insert (context->filesystems, g_strdup (key), value);

programming_language: C