Description The addressbook file backend implementation in e-book-backend-file.c manages contact photo and logo files stored on disk. When a contact is created or modified, inline image data is converted to a file on disk and the vCard is updated with a file URI pointing to the stored file. When a contact is deleted or its image changes, the old file is removed from disk. Both the PHOTO and LOGO vCard fields go through this same code path. Two different functions implement security checks on these URIs, using inconsistent comparison logic. During contact creation and modification, maybe_transform_vcard_field_for_photo() calls is_backend_owned_uri() to determine whether an incoming URI belongs to the backend. This function extracts the directory component with g_path_get_dirname() and performs an exact match against the photo directory using strcmp(): dirname = g_path_get_dirname (filename); owned_uri = bf->priv->photo_dirname && (strcmp (dirname, bf->priv->photo_dirname) == 0); A URI containing ../ sequences will not match, so is_backend_owned_uri() returns FALSE. The URI is then stored verbatim in the SQLite database without transformation. During contact deletion, book_backend_file_remove_contacts_sync() calls maybe_delete_unused_uris(), which retrieves the stored URIs for both the E_CONTACT_PHOTO and E_CONTACT_LOGO fields via check_remove_uri_for_field() and passes each to maybe_delete_uri(). This function performs a prefix match on the raw, unresolved path using strncmp(): if (bf->priv->photo_dirname && !strncmp (bf->priv->photo_dirname, filename, strlen (bf->priv->photo_dirname))) { d (g_print ("Deleting uri file: %s\n", filename)); /* Deleting uris should not cause the backend to fail to update * a contact so the best we can do from here is log warnings * when we fail to unlink a file from the disk. */ if (!remove_file (filename, &error)) { g_warning ("Unable to cleanup photo uri: %s", error->message); g_error_free (error); } } Since strncmp() only checks that the path starts with the photo directory, a URI containing ../ sequences after the prefix will pass this check. The remove_file() function then calls g_unlink(), which resolves the ../ sequences, deleting the traversed target file. Because maybe_delete_unused_uris() processes both fields independently, a single contact can be used to delete two arbitrary files in one operation. The Evolution backend server exposes the D-Bus service org.gnome.evolution.dataserver.AddressBook, that can be used in order to manage contacts. A Flatpak application with access to this D-Bus service can exploit this issue in order to gain arbitrary file deletion on the host filesystem. A simple proof of concept script shhowcasing this issue can be found in the attached file. Impact A Flatpak application with D-Bus access to the addressbook service can delete arbitrary files on the host, potentially including Flatpak override files, which are typically used to remove permissions at varying levels of granularity, from app-specific to user- or system-wide. Recommended solution Canonicalize the file path in maybe_delete_uri() using realpath() before performing the prefix comparison, ensuring that ../ sequences are resolved.