GRUB2-BLS in openSUSE Tumbleweed is now the default
openSUSE Tumbleweed recently changed the default boot loader from GRUB2 to GRUB2-BLS when installed via YaST.
This follows the trend started by MicroOS of adopting boot loaders that are compatible with the boot loader specification. MicroOS is using systemd-boot, which is a very small and fast boot loader from the systemd project.
One of the reasons for this change is to simplify the integration of new features. Among them is full disk encryption based on systemd tools, which will make use of TPM2 or FIDO2 tokens if they are available.
What is GRUB2-BLS
GRUB2-BLS is just GRUB2 but with some patches on top ported from the Fedora project, which includes some compatibility for the boot loader specification for Type #1 boot entries. Those are small text files stored in /boot/efi/loader/entries that the boot loader reads to present the initial menu.
Each file contains a reference to the kernel, the initrd, and the kernel command line that will be used to boot the system. It can be edited directly by the user or managed by tools like bootctl and sdbootutil.
In the next version of GRUB2 (2.14), those patches will be included as part of the project itself, and the upgrade process will be transparent for the final user.
It should be noted that the way openSUSE deploys GRUB2-BLS is different from the classical GRUB2. GRUB2-BLS is deployed as a single EFI binary installed (copied) in /boot/efi/EFI/opensuse that will have embedded all the resources (like the modules, configuration file, fonts, themes and graphics), which were previously placed in /boot/grub2.
Installation
The good news is that with the latest version of YaST the process is automatic. The user just needs to follow the default steps and the system will be based on GRUB2-BLS at the end.
The installer will first propose a large ESP partition of about 1GB. This is required because all the kernel and initrds will now be placed in the FAT32 ESP partition located in /boot/efi/opensuse-tumbleweed.
Of course the user can select a different boot loader during the installation like the classical GRUB2 or systemd-boot. This can be done in the “Installation Settings” screen presented at the end of the installation proposal. Just select the “Booting” header link and choose your boot loader from there.
Full disk encryption
When using a BLS boot loader, we can now install the system with full disk encryption (FDE) based on systemd. This can be done from the “Suggested Partitioning” screen. Just press “Guided Setup” and in the “Partitioning Scheme” select “Enable Disk Encryption”.
From there, you can set a LUKS2 password and, optionally, enroll a security device like a TPM2 or a FIDO2 key. For laptops, it is recommended to enroll the system with a TPM2+PIN. The TPM2 will first assert that the system is in a healthy (known) state. Than means that elements used during the boot process (from the firmware until the kernel) are the expected ones, and no one tampered with them. After that, the TPM2 will ask for a PIN or password, which YaST will set as the one entered for the LUKS2 key slot.
Usage
With GRUB2-BLS, we will no longer have grub2 tools like grub2-mkconfig or grub2-install. Most of them are not required anymore. Boot entries are generated dynamically by the boot loader, so there is no longer any need to generate GRUB2 configuration files, and the installation is just copying the new EFI file into the correct location.
The upgrade process is also done by automatically calling sdbootutil update from the snapper plugins or the SUSE module tools, so if btrfs is used, all the management will be done transparently by this infrastructure, as was done in the traditional boot loader.
Updating the kernel command line can now be done by editing the boot loader, or the /etc/kernel/cmdline and calling sdbootutil update-all-entries to propagate the change into the boot entries of the current snapshot.
To manage the FDE configuration, you can learn more in the openSUSE wiki.
How to Create an MCP Server
How to Create an MCP Server
This guide is for developers who want to build a MCP server. It describes how to implement an MCP for listing and adding users.
What Is an MCP Server?
An MCP server is a wrapper that sits between a Large Language Model (LLM) and an application, wrapping calls from the LLM to the application in JSON. You might be tempted to wrap your application’s existing APIs via fastapi and fastmcp, but as described by mostly harmless, this is a bad idea.
The main reason for this is that an LLM performs text completion based on the “downloaded” internet and can focus on a topic for no more than approximately 100 pages of text. It’s hard to fill these pages with chat, and you may have never encountered this limit. This also means that you need a user story or tasks to fill this book, including all possible failures and dead ends. In our example, we will add a user "tux" to the system.
The first pages of this imaginary book are already filled by the system prompt and the description of the MCP tool and its parameters. This description is provided by the tool’s author, so you can be very descriptive when writing the tool descriptions. A few more lines of text won’t hurt.
Every tool call has a JSON overlay, so you also want to avoid too many tool calls. Try to minimize the number of tools and combine similar operations into a single tool. For example, if you had a tool interacting with systemd, you would have just one tool that combines enabling, disabling, starting, and restarting the service, rather than one tool for each operation.
For the tool output, don’t hesitate to combine as much information as possible. A good tool’s output shouldn’t just return the group ID (GID) but also the group name.
The caveat here is that you can easily oversaturate the LLM with too much information, such as returning the output of find /. This would completely fill the imaginary book of the LLM conversation. In such cases, trim the information and provide parameters for tools, like filtering the output.
This boils down to the following points:
- Have a user story for the tools.
- Provide extensive descriptions for tools and their parameters.
- Condense tools into sensible operations and don’t hesitate to add many parameters.
- A tool call can have several API calls.
- Avoid overload: LLMs can’t ignore output, so you are responsible for trimming information. And also the following bonus point, which I learned along the way:
- Avoid a
verboseparameter; an LLM will always use it.
== Always remember: ==
== “Context is King” ==
Build a Sample MCP Server
User Story
First, we have to come up with a user story. We have to decide what the user should be capable of doing with the tool.
Our user story is quite simple: “I want to add a user to the system.”
First Step
We will use Go for this project and start with this simple boilerplate code, which adds the tool “Foo”:
package main
import (
"context"
"flag"
"log/slog"
"net/http"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// Input struct for the Foo tool.
type FooInput struct {
Message string `json:"message,omitempty" jsonschema:"a message for the Foo tool"`
}
// Output struct for the Foo tool.
type FooOutput struct {
Response string `json:"response" jsonschema:"the response from the Foo tool"`
}
// Foo function implements the Foo tool.
func Foo(ctx context.Context, req *mcp.CallToolRequest, input FooInput) (
*mcp.CallToolResult, FooOutput, error,
) {
slog.Info("Foo tool called", "message", input.Message)
return nil, FooOutput{Response: "Foo received your message: " + input.Message}, nil
}
func main() {
listenAddr := flag.String("http", "", "address for http transport, defaults to stdio")
flag.Parse()
server := mcp.NewServer(&mcp.Implementation{Name: "useradd", Version: "v0.0.1"}, nil)
mcp.AddTool(server, &mcp.Tool{
Name: "Foo",
Description: "A simple Foo tool",
}, Foo)
if *listenAddr == "" {
// Run the server on the stdio transport.
if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
slog.Error("Server failed", "error", err)
}
} else {
// Create a streamable HTTP handler.
handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server {
return server
}, nil)
// Run the server on the HTTP transport.
slog.Info("Server listening", "address", *listenAddr)
if err := http.ListenAndServe(*listenAddr, handler); err != nil {
slog.Error("Server failed", "error", err)
}
}
}
To run the server, we first have to initialize the Go dependencies with:
go mod init github.com/mslacken/mcp-useradd
go mod tidy
Now the server can be run with the command:
go run main.go -http localhost:8666
And we can run a JavaScript-based explorer in an additional terminal via:
npx @modelcontextprotocol/inspector http://localhost:8666 --transport http
This gives us the following screen after the ‘Foo’ tool with the input ‘Baar’ was called.

Let’s break down our Go code. After the imports, we immediately have two structs that manage the input and output for our tool. Go has a built-in serializer for data structures. The keyword json:"message,omitempty" tells the serialization library to use “message” as the variable’s name. More important is the second option, “omitempty,” which marks this as an optional input parameter; if empty, the variable won’t be in the output. The “jsonschema” parameter describes what this parameter does and what input is expected. Although the parameter’s type is deduced from the struct, the description is crucial. The method for the tool returns the message by constructing the output struct and returning it.
The method itself is added to the MCP server instance and also needs to have a name and a description. The description of the tool is also highly important and is the only way for the LLM to know what the tool is doing.
Concretize the tool
The full code of this section can be found in the git commit simple user list
As we don’t want to change the system at this early phase and the whole project would need a tool to get the actual users of the system. So let’s add the tool get_users.
To keep it simple we just use we will just use the output of getent passwd to fullfill this task.
A function which can do this would look like
// User struct represents a single user account.
type User struct {
Username string `json:"username"`
Password string `json:"password"`
UID int `json:"uid"`
GID int `json:"gid"`
Comment string `json:"comment"`
Home string `json:"home"`
Shell string `json:"shell"`
}
func ListUsers(ctx context.Context, req *mcp.CallToolRequest, _ ListUsersInput) (
*mcp.CallToolResult, ListUsersOutput, error,
) {
slog.Info("ListUsers tool called")
cmd := exec.Command("getent", "passwd")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, ListUsersOutput{}, err
}
var users []User
scanner := bufio.NewScanner(&out)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
if len(parts) != 7 {
continue
}
uid, _ := strconv.Atoi(parts[2])
gid, _ := strconv.Atoi(parts[3])
users = append(users, User{
Username: parts[0],
Password: parts[1],
UID: uid,
GID: gid,
Comment: parts[4],
Home: parts[5],
Shell: parts[6],
})
}
return nil, ListUsersOutput{Users: users}, nil
}
When you check this method you see that output is just a list (called slice in go) of the users and their porperties.
Although this looks correct this method is missing some important things
- the user type, is it a system or user an user account of a human
- in which groups is the user part of
Asking such type of questions and then providing that information is the most important part when writing an MCP tool. This information isn’t known to the LLM but might define the input paramters when adding an user.
In opposite to a real implementation of such a tool will just treat all users with a ‘gid < 1000’ as system users.
Also we all add a call to getent group to get all groups in which the user is part of.
When now this tools is called it’s also sensible to output the group information, as this would enable the LLM to fullfill the taks like “Add the user chris to the system and make him part of the witcher group”.
The full code of this section can be found in the git commit better user list
With that information the tool call now likes
// ListUsers function implements the ListUsers tool.
func ListUsers(ctx context.Context, req *mcp.CallToolRequest, _ ListUsersInput) (
*mcp.CallToolResult, ListUsersOutput, error,
) {
slog.Info("ListUsers tool called")
cmd := exec.Command("getent", "passwd")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, ListUsersOutput{}, err
}
var users []User
scanner := bufio.NewScanner(&out)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
if len(parts) != 7 {
continue
}
uid, _ := strconv.Atoi(parts[2])
gid, _ := strconv.Atoi(parts[3])
users = append(users, User{
Username: parts[0],
Password: parts[1],
UID: uid,
GID: gid,
Comment: parts[4],
Home: parts[5],
Shell: parts[6],
IsSystemUser: gid < 1000,
Groups: []string{},
})
}
cmd = exec.Command("getent", "group")
var groupOut bytes.Buffer
cmd.Stdout = &groupOut
err = cmd.Run()
if err != nil {
return nil, ListUsersOutput{}, err
}
var groups []Group
groupScanner := bufio.NewScanner(&groupOut)
for groupScanner.Scan() {
line := groupScanner.Text()
parts := strings.Split(line, ":")
if len(parts) != 4 {
continue
}
gid, _ := strconv.Atoi(parts[2])
members := strings.Split(parts[3], ",")
groups = append(groups, Group{
Name: parts[0],
Password: parts[1],
GID: gid,
Members: members,
})
groupName := parts[0]
for _, member := range members {
for i, user := range users {
if user.Username == member {
users[i].Groups = append(users[i].Groups, groupName)
}
}
}
}
return nil, ListUsersOutput{Users: users, Groups: groups}, nil
}
The result looks now like

This is gives now the LLM much more sensible information about the system and e.g. if I would aks “Add chris to the system and add him to the witcher group” and on the system wouldn’t be the group ‘witcher’ but on called ‘hexer’ it could find out that it’s german system and perhaps ‘hexer’ would be right group then.
As icing of the cake we now refactor the list method so that a username can be passed as an optional paramater. In such way the output of the tool can be limited. This is important for many subsequent tools calls. For real production garde software the paramter would then also regular expressions or even fuzzy matching. The full code of this section can be found in the git commit filter with a username This transforms the tool call to
// ListUsers function implements the ListUsers tool.
func ListUsers(ctx context.Context, req *mcp.CallToolRequest, input ListUsersInput) (
*mcp.CallToolResult, ListUsersOutput, error,
) {
slog.Info("ListUsers tool called")
users, err := getUsers(input.Username)
if err != nil {
return nil, ListUsersOutput{}, err
}
if input.Username != "" {
return nil, ListUsersOutput{Users: users}, nil
}
groups, err := getGroups()
if err != nil {
return nil, ListUsersOutput{}, err
}
for _, group := range groups {
for _, member := range group.Members {
for i, user := range users {
if user.Username == member {
users[i].Groups = append(users[i].Groups, group.Name)
}
}
}
}
return nil, ListUsersOutput{Users: users, Groups: groups}, nil
}
func getUsers(username string) ([]User, error) {
args := []string{"passwd"}
if username != "" {
args = append(args, username)
}
cmd := exec.Command("getent", args...)
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
var users []User
scanner := bufio.NewScanner(&out)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
if len(parts) != 7 {
continue
}
uid, _ := strconv.Atoi(parts[2])
gid, _ := strconv.Atoi(parts[3])
users = append(users, User{
Username: parts[0],
Password: parts[1],
UID: uid,
GID: gid,
Comment: parts[4],
Home: parts[5],
Shell: parts[6],
IsSystemUser: gid < 1000,
Groups: []string{},
})
}
if username != "" && len(users) > 0 {
groups, err := getUserGroups(username)
if err == nil {
users[0].Groups = groups
}
}
return users, nil
}
Still there are many things we could add here as parameter like filtering for non system users only, check for ‘pam.d’ options which interacts with users…
Adding a user
Just for completeness we now add a tool for adding user, which does this by the SUSE specific useradd call.
The full code of this section can be found in the git commit added user add method
A tool can look like
// Input struct for the AddUser tool.
type AddUserInput struct {
Username string `json:"username" jsonschema:"the username of the new account"`
BaseDir string `json:"base_dir,omitempty" jsonschema:"the base directory for the home directory of the new account"`
Comment string `json:"comment,omitempty" jsonschema:"the GECOS field of the new account"`
HomeDir string `json:"home_dir,omitempty" jsonschema:"the home directory of the new account"`
ExpireDate string `json:"expire_date,omitempty" jsonschema:"the expiration date of the new account"`
Inactive int `json:"inactive,omitempty" jsonschema:"the password inactivity period of the new account"`
Gid string `json:"gid,omitempty" jsonschema:"the name or ID of the primary group of the new account"`
Groups []string `json:"groups,omitempty" jsonschema:"the list of supplementary groups of the new account"`
SkelDir string `json:"skel_dir,omitempty" jsonschema:"the alternative skeleton directory"`
CreateHome bool `json:"create_home,omitempty" jsonschema:"create the user's home directory"`
NoCreateHome bool `json:"no_create_home,omitempty" jsonschema:"do not create the user's home directory"`
NoUserGroup bool `json:"no_user_group,omitempty" jsonschema:"do not create a group with the same name as the user"`
NonUnique bool `json:"non_unique,omitempty" jsonschema:"allow to create users with duplicate (non-unique) UID"`
Password string `json:"password,omitempty" jsonschema:"the encrypted password of the new account"`
System bool `json:"system,omitempty" jsonschema:"create a system account"`
Shell string `json:"shell,omitempty" jsonschema:"the login shell of the new account"`
Uid int `json:"uid,omitempty" jsonschema:"the user ID of the new account"`
UserGroup bool `json:"user_group,omitempty" jsonschema:"create a group with the same name as the user"`
SelinuxUser string `json:"selinux_user,omitempty" jsonschema:"the specific SEUSER for the SELinux user mapping"`
SelinuxRange string `json:"selinux_range,omitempty" jsonschema:"the specific MLS range for the SELinux user mapping"`
}
func AddUser(ctx context.Context, req *mcp.CallToolRequest, input AddUserInput) (
*mcp.CallToolResult, AddUserOutput, error,
) {
slog.Info("AddUser tool called")
args := []string{}
if input.BaseDir != "" {
args = append(args, "-b", input.BaseDir)
}
/*
Cutted a lot of command line parameter settings
*/
if input.SelinuxUser != "" {
args = append(args, "-Z", input.SelinuxUser)
}
args = append(args, input.Username)
cmd := exec.Command("useradd", args...)
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &out
err := cmd.Run()
if err != nil {
return nil, AddUserOutput{Success: false, Message: out.String()}, err
}
return nil, AddUserOutput{Success: true, Message: out.String()}, nil
}
For a real MCP server the tool could also be aware of the standard home location and provide the btrfs related option on ly on these and the same holds true if SELinux is enabled or not and then just add these options. But I think it’s now clear how the coockie crumbles for MCP tools.
Episodio 59 de KDE Express: Plasma 6.5 con muchas actualizaciones de apps
Me congratula presentaros el episodio 59 de KDE Express, titulado «Plasma 6.5 con muchas actualizaciones de apps » donde David Marzal nos trae un episodio lleno de novedades y no solo de la Comunidad KDE. Es que el mundo del Software Libre no para.
Episodio 59 de KDE Express: Plasma 6.5 con muchas actualizaciones de apps
Comenté hace ya bastante tiempo que había nacido KDE Express, un audio con noticias y la actualidad de la Comunidad KDE y del Software Libre con un formato breve (menos de 30 minutos) que complementan los que ya generaba la Comunidad de KDE España, aunque ahora estamos tomándonos un tiempo de respiro por diversos motivos, con sus ya veteranos Vídeo-Podcast que todavía podéis encontrar en Archive.org, Youtube, Ivoox, Spotify y Apple Podcast.
De esta forma, a lo largo de estos 45 episodios, promovidos principalmente por David Marzal, nos han contado un poco de todo: noticias, proyectos, eventos, etc., convirtiéndose (al menos para mi) uno de los podcast favoritos que me suelo encontrar en mi reproductor audio.
En palabras de David:

Viajamos en el tiempo saltándonos un episodio (que al ser especial os lo dejamos para la semana que viene). Y en el de hoy os hablamos de KDE Plasma 6.5 y muchas aplicaciones de las cuales os dejamos los enlaces a las noticias originales a continuación.
LineageOS 23.0 ha sido publicada no sin dificultad por las trabajas que está poniendo Google, ahora tenemos menos seguridad y es más complicado hacer ROMs de Android.
- Transiciones de temas automáticas: cambio automático del tema claro al oscuro según la hora del día.
- Navegación de texto de cursor
- Búsqueda difusa de KRunner
- Elementos fijados en el portapapeles
- Página Permisos de Flatpak transformada en una página general de Permisos de aplicaciones, donde se puede configurar la capacidad de las aplicaciones para hacer cosas como realizar capturas de pantalla y aceptar solicitudes de control remoto.
- Actualizada la página Wifi y redes de las Preferencias del sistema para que muestre las redes inalámbricas detectadas
- El lector de pantalla Orca puede leer ahora los cambios de estado del bloqueo de mayúsculas
- Discover ha ganado compatibilidad con las URL de tipo flatpak+https, lo que permite que los botones «Instalar» de Flathub abran Discover automáticamente. También puede mostrar los controladores de hardware disponibles para instalar en los sistemas operativos que sean compatibles con esta funcionalidad.
- El selector de emojies ahora te deja buscarlos en inglés si tu idioma es otro.
- Mejora del núcleo de la aplicación portada a Qt 6.10.0 para mejor rendimiento y estabilidad.
- Control de etiquetas, con jerarquías y posibilidad de exportar e importar desde formato texto.
- Ahora se usa automáticamente el perfil de color de tu monitor
- Mejoras en el Editor y los Plugins; con una herramienta de desenfoque progresivo del fondo de una foto por ejemplo.
Kaidan 0.13 (cliente XMPP) trae muchas novedades como, soporte multicuenta, marcar mensajes, almacenamineto seguro de contraseñas, reenviar mensajes…
Haruna 1.6 mejora las listas y opciones reproducción, junto con algún retoque al manejo del ratón.
Krita añade soporte HDR en Wayland.
KRetro una interfaz gráfica para libreto (una piedra roseta de emuladores). Está en Kirigami así que servirá tanto para Escritorio como para Moviles o Bigscreen cuando esté empaquetado.
LinuxAdictos nos recomienda probar el tablero de aplicaciones en vez del menu normal de aplicaciones
Le damos la bienvenida a Carl Schwan y David Redondo y las gracias a Nate Graham y Adriaan de Groot por su tiempo en KDE E.V.
KDE Linux y los gestores de paquetes tradicionales.
LXQt como proyecto pequeño y modular no puede crear un compositor wayland, pero se integra con 7 con diferentes funcionalidades. Por ahora el que más ofrece es, sorpresa, Kwin.
Como instalar Plasma 6.5 en Kubuntu 25.10.
Recopilatorio de experiencias de Akademy Internacional
- https://blogs.kde.org/2025/10/07/akademy-2025/
- https://euroquis.nl/kde/2025/10/14/akademy.html
- https://merritt.codes/blog/2025/09/19/2025/_akademy-2025
- https://alex1701c.github.io/2025/09/21/akademy-2025.html
- https://www.volkerkrause.eu/2025/09/20/kde-akademy-2025.html
- https://redstrate.com/blog/2025/09/akademy-2025/
- https://blog.seshan.xyz/2025/09/15/my-akademy-2025-trip-to-berlin/
Firefox 144 mejoras en las pestañas y un administrador de perfiles.
Y junto a el Thunderbird 144 también ha sido publicado: Mejoras en flatpak y muchos arreglos.
openSUSE es reconocida como Bien Público Digital
Adios YaST, molabas mucho.
Por cierto, también podéis encontrarlos en Telegram: https://t.me/KDEexpress
La entrada Episodio 59 de KDE Express: Plasma 6.5 con muchas actualizaciones de apps se publicó primero en KDE Blog.
lightdm-kde-greeter: Privilege Escalation from lightdm Service User to root in KAuth Helper Service (CVE-2025-62876)
Table of Contents
- 1) Introduction
- 2) Overview of the D-Bus Helper
- 3) Problems in the D-Bus Helper
- 4) Upstream Bugfix
- 5) CVE Assignment
- 6) Coordinated Disclosure
- 7) Timeline
- 8) References
1) Introduction
lightdm-kde-greeter is a KDE-themed greeter application for the lightdm display manager. At the beginning of September one of our community packagers asked us to review a D-Bus service contained in lightdm-kde-greeter for addition to openSUSE Tumbleweed.
In the course of the review we found a potential privilege escalation from the
lightdm service user to root which is facilitated by this D-Bus service,
among some other shortcomings in its implementation.
The next section provides a general overview of the D-Bus service. Section 3 discusses the security problems in the service’s implementation. Section 4 takes a look at the bugfix upstream arrived at.
This report is based on lightdm-kde-greeter release 6.0.3.
2) Overview of the D-Bus Helper
lightdm-kde-greeter includes a D-Bus service which enables regular users to configure custom themes to be used by the greeter application. The D-Bus service is implemented as a KDE KAuth helper service, running with full root privileges.
The helper implements a single API method, protected by
Polkit action org.kde.kcontrol.kcmlightdm.save, which requires
auth_admin_keep by default, i.e. users need to provide root credentials to
perform this action. The method takes a map of key/value pairs which allow to
fully control the contents of lightdm.conf and lightdm-kde-greeter.conf.
From a security point of view such a generic interface is sub-optimal, since the scope of the operation is not restricted to changing theme settings, but also allows to change all the rest of lightdm’s configuration, providing less control over who may do what in the system. From an application’s point of view this approach is understandable, however, as this makes it easy to support any future features.
Another Polkit action org.kde.kcontrol.kcmlightdm.savethemedetails is
declared in kcm_lightdm.actions, which is unused, maybe
a remnant of former versions of the project.
3) Problems in the D-Bus Helper
The problems in the D-Bus service start in helper.cc line 87, where we can find this comment:
// keys starting with "copy_" are handled in a special way, in fact,
// this is an instruction to copy the file to the greeter's home
// directory, because the greeter will not be able to read the image
// from the user's home folder
To start with it is rather bad API design to abuse the key/value map, which is supposed to contain configuration file entries, for carrying “secret” copy instructions. Even worse, in the resulting copy operation three different security contexts are mixed:
- the helper, which runs with full root privileges.
- the unprivileged D-Bus client, which specifies a path to be opened by the helper.
- the
lightdmservice user; the helper will copy the user-specified file into a directory controlled by it.
The helper performs this copy operation with full root privileges without
taking precautions, reading input data from one unprivileged context and
writing it into another unprivileged context. This is done naively using
the Qt framework’s QFile::copy() and similar APIs, leading to a range of
potential local attack vectors:
- Denial-of-Service (e.g. passing a named FIFO pipe as source file path, causing the D-Bus helper to block indefinitely).
- information leak (e.g. passing a path to private data as source file like
/etc/shadow, which will then become public in/var/lib/lightdm). - creation of directories in unexpected locations (the helper attempts to
create
/var/lib/lightdm/.../<theme>, thus the lightdm user can place symlinks there which will be followed). - overwrite of unexpected files (similar as before, symlinks can be placed as destination file name, which will be followed and overwritten with client data).
If this action would ever be set to yes Polkit authentication requirements,
then this would be close to a local root exploit. Even in its existing form it
allows the lightdm service user to escalate privileges to root.
Interestingly these problems are quite similar to issues in sddm-kcm6, which
we covered in a previous blog post.
4) Upstream Bugfix
We suggested the following changes to upstream to address the problems:
- the copy operation should be implemented using D-Bus file descriptor
passing, this way opening client-controlled paths as
rootis already avoided. - for creating the file in the target directory of
lightdm, a privilege drop to thelightdmservice user should be performed to avoid any symlink attack surface.
We are happy to share that the upstream maintainer of lightdm-kde-greeter
followed our suggestions closely and coordinated the changes with us before
the publication of the bugfix. With these changes, this KAuth helper is now
kind of a model implementation which can serve as a positive example for other
KDE components. Upstream also performed some general cleanup, like the removal
of the unused savethemedetails Polkit action from the repository.
Upstream released version 6.0.4 of lightdm-kde-greeter which contains the fixes.
5) CVE Assignment
In agreement with upstream, we assigned CVE-2025-62876 to track the lightdm
service user to root privilege escalation aspect described in this report.
The severity of the issue is low, since it only affects defense-in-depth (if
the lightdm service user were compromised) and the problematic logic can
only be reached and exploited if triggered interactively by a privileged user.
6) Coordinated Disclosure
We reported these issues to KDE security on 2025-09-04 offering coordinated disclosure, but we initially had difficulties setting up the process with them. Upstream did not clearly express the desire to practice coordinated disclosure, no (preliminary) publication date could be set and no confirmation of the issues was received.
Things took a turn for the better when a lightdm-kde-greeter developer contacted us directly on 2025-10-16 and the publication date and fixes were discussed. The ensuing review process for the bugfixes was very helpful in our opinion, leading to a major improvement of the KAuth helper implementation in lightdm-kde-greeter.
7) Timeline
| 2025-09-04 | We received the review request for the lightdm-kde-greeter D-Bus service. |
| 2025-09-10 | We privately reported the findings to KDE security. |
| 2025-09-17 | We received an initial reply from KDE security stating that they would get back to us. |
| 2025-09-29 | We asked for at least a confirmation of the report and a rough disclosure date, but upstream was not able to provide this. |
| 2025-10-01 | KDE security informed us that an upstream developer planned to release fixes by mid-November. |
| 2025-10-16 | An upstream developer contacted us to discuss the publication date, since the bugfixes were ready. |
| 2025-10-20 | We asked the developer to share the bugfixes for review. |
| 2025-10-21 | The developer shared a patch set with us. |
| 2025-10-24 | We agreed on 2025-10-31 for coordinated disclosure date. |
| 2025-10-28 | After a couple of email exchanges discussing the patches, upstream arrived at an improved patch set. We suggested to assign a CVE for the ligthdm to root attack surface. |
| 2025-10-29 | We assigned CVE-2025-62876. |
| 2025-11-03 | We asked when the bugfix release would be published, with the disclosure date already passed. |
| 2025-11-03 | Upstream agreed to publish on the same day. |
| 2025-11-03 | Upstream released version 6.0.4 containing the bugfixes. We published our Bugzilla bug on the topic. |
| 2025-11-13 | Publication of this report. |
8) References
Las nuevas funcionalidades de Plasma 6.5
Hace ya dos semanas que fue lanzado el nuevo entorno de escritorio de la Comunidad KDE y todavía no he tenido tiempo para difundirlas como se merece. Empiezo hoy la serie con las mismas empezando con las nuevas funcionalidades de Plasma 6.5, un extenso repaso a todo el gran trabajo del equipo de desarrolladores de KDE.
Las nuevas funcionalidades de Plasma 6.5
Plasma 6.5 ya es un entorno de trabajo maduro, robusto y lleno de funcionalidades, pero los desarrolladores no dejan de añadirle más. Hagamos un repaso exhaustivo:
La primera de ellas es visual, la posibilidad de tener esquinas redondeadas en la parte inferior de las ventanas. De esta forma, las ventanas que usan el tema Brisa tendrán ahora el mismo nivel de redondez en las cuatro esquinas. No entiendo porque si se hizo esto con las esquina superiores no se hizo con la inferiores, pero seguro que hay una explicación lógica. Evidentemente, si no te gusta, también puede hacer que no sean redondas.

Por otra parte, ahora tenemos el cambio automático del tema claro al oscuro según la hora del día. Se pueden configurar los temas entre los que se cambia y también los temas que se muestran para el cambio manual en la página Ajustes rápidos de las Preferencias del sistema. Además, también se puede configurar si el fondo del escritorio cambia entre sus versiones clara y oscura según el esquema de color, la hora del día, o que siempre sea claro u oscuro.

Una función muy interesante que se ha implementado es que ahora se pueden tener «elementos fijados en el portapapeles», lo que permite guardar en el portapapeles textos que se usen con frecuencia para que no tenga que estar copiándolos una y otra vez. Ya he utilizado esta funcionalidad y me parece fabulosa: para correcciones, para edición html, para notas recurrentes, etc.

También hay novedades para los artistas, ya que ahora se pueden configurar los diales rotatorios y los anillos táctiles de las tabletas de dibujo en la página Tableta de dibujo de las Preferencias del sistema. También se muestra una advertencia cuando se intenta configurar una tableta gestionada por un controlador personalizado. Además, la página de la tableta se oculta si no se ha conectado una tableta de dibujo previamente. Cuando mi hijo tenga una tableta de este tipo lo podré probar.
En ocasiones los cambios en las funcionalidades nos hacen ver que hay funciones que ni sabíamos que existían. Pocas personas saben que Plasma tiene una página Permisos de Flatpak que ahora se muestra en una página general de Permisos de aplicaciones, donde se puede configurar la capacidad de las aplicaciones para hacer cosas como realizar capturas de pantalla y aceptar solicitudes de control remoto.

Para finalizar alguna funciones sencillas:
- Ahora servidor integrado del protocolo de escritorio remoto (RDP) de Plasma le permite ahora compartir el portapapeles.
- La utilidad que lee el nivel de tinta o de tóner de la impresora le informa ahora cuando se está agotando o cuando está vacío.
- Finalmente, ahora se puede hibernar el sistema desde la pantalla de inicio de sesión.
Más información: Plasma 6.5
La entrada Las nuevas funcionalidades de Plasma 6.5 se publicó primero en KDE Blog.
openSUSE Tumbleweed
openSUSE Tumbleweed recently changed the default boot loader from GRUB2 to GRUB2-BLS when installed via YaST.
This follows the trending started by MicroOS of adopting boot loaders that are compatible with the boot loader specification. MicroOS is using systemd-boot, a very small and fast boot loader from the systemd project.
One of the reasons of this change is that simplify the integration of new features, like a full disk encryption based on the systemd tools, that will make use of the TPM2 or FIDO2 tokens if they are available.
What is GRUB2-BLS
GRUB2-BLS is just GRUB2 but with some patches on top ported from the Fedora project, that includes some compatibility for the boot loader specification for Type #1 boot entries. Those are small text files stored in /boot/efi/loader/entries that the boot loader reads to present the initial menu.
Each file contains a reference to the kernel, the initrd and the kernel command line that will be used to boot the system, and can be edited directly by the user or managed by tools like bootctl and sdbootutil.
The next version of GRUB2 (2.14) those patches will be included as part of the project itself, and the upgrade process will be transparent for the final user.
Should be noted that the way that openSUSE deploy GRUB2-BLS is different from the classical GRUB2. GRUB2-BLS is deployed as a single EFI binary installed (copied) in /boot/efi/EFI/opensuse that will have embedded all the resources (like the modules, configuration file, fonts, themes and graphics) that previously where placed in /boot/grub2.
Installation
The good news is that with the last version of YaST the process is automatic. The used just needs to follow the default steps and the system will be based on GRUB2-BLS at the end.
The installed will propose first a large ESP partition of about 1GB. This is required because now all the kernel and initrds will be placed in the FAT32 ESP partition, in /boot/efi/opensuse-tumbleweed.
Of course the user can select during the installation a different boot loader, like the classical GRUB2 or systemd-boot. This can be done in the “Installation Settings” screen presented at the end of the installation proposal. Just select the “Booting” header link and choose your boot loader from there.
Usage
With GRUB2-BLS we will not have anymore the grub2 tools, like grub2-mkconfig or grub2-install. Most of them are not required anymore. The boot entries are generated dynamically by the boot loader, so there is no need anymore of generating GRUB2 configuration files, and the installation is just copying the new EFI file into the correct place.
The upgrade process is also done automatically calling sdbootutil update by the snapper plugins or the SUSE module tools, so if btrfs is used all the management will be done transparently by this infrastructure, as was done in the traditional boot loader.
Updating the kernel command line can be now be done by editing the boot loader, or the /etc/kernel/cmdline and calling sdbootutil update-all-entries to propagate the change into the boot entries of the current snapshot.
Hack Week Project Seeks to Launch Kudos
A new Hack Week 25 project aims to display appreciation and recognition for contributors across the openSUSE Project.
Called Kudos, the application is designed to give members of the project an easy way to acknowledge contributions beyond code submissions alone.
Lubos Kocman joked during the naming discussion that “We also had an option to call it ReKognize and have a Mortal Kombat announcer behind the menu items.”
Kudos began shortly after the release of Leap 16.0 with the goal of creating a simple and friendly way for community members to thank one another for their efforts and contributions.
As a Release Manager, Kocman and other release managers have long recognized core Leap contributors after each release.
“We used to send people Leap DVD boxes,” he said, but these DVDs are no longer produces.
An internal SUSE recognition platform allows for employees to acknowledge one another since DVDs were no longer an option. Kocman began sending emails mimicing SUSE’s recognition messages.
“But at some point I was fed up and thought to myself, we can do better,” Kocman said, who created the Kudos Hack Week project.
He notes that openSUSE relies on extensive, often invisible efforts. These include contributions with translations, documentation updates, wiki curation, infrastructure maintenance, moderation, booth staffing, testing, talks, and countless other efforts that rarely show up in a traditional form of recongition.
Kudos aims to bring those contributions into the light.
The visablity of these recogniztion will take place in areas where members of the project communicate. Sharing could take place on chat.opensuse.org, on social media through bots, Slack, and other options, which will be explored during Hack Week and beyond.
Kudos resources include the application’s source code, a dedicated badge repository, and an issue tracker. Existing badge templates can be used, but the maintainer asks participants not to create new badge requests during Hack Week unless they also plan to complete them during the event.
Developers and contributors interested in participating can join or follow the project’s progress through the GitHub repositories.

Hack Week, which began in 2007, has become a cornerstone of the project’s open-source culture. Hack Week has produced tools that are now integral to the openSUSE ecosystem, such as openQA, Weblate and Aeon Desktop. Hack Week has also seeded projects that later grew into widely used products; the origins of ownCloud and its fork Nextcloud derive from a Hack Week project started more than a decade ago.
For more information, visit hackweek.opensuse.org.
Setkání překladatelů software z angličtiny do češtiny na LinuxDays
Chybí lidé a aktuální dokumentace, shodli se překladatelé na LinuxDays
To, že na nás náš svobodný software mluví česky není samozřejmost, ale výsledek dlouhodobé práce řady překladatelů. Je to činnost, která vyžaduje dobrou znalost angličtiny, češtiny, i linuxového softwaru.
Sexta actualización de Plasma 6.4
Me alegra compartir con todos vosotros la sexta actualización de Plasma 6.4, iniciando así una serie de revisión de software que le dotará de más estabilidad, mejores traducción y resolución de errores. Estas actualizaciones son 100% recomendables y casi obligatorias para cualquier usuario ya que lo único que hacen es mejorar la versión sin comprometer sus funcionalidades.
Sexta actualización de Plasma 6.4
No existe Software creado por la humanidad que no contenga errores. Es un hecho incontestable y cuya única solución son las actualizaciones. Es por ello que en el ciclo de desarrollo del software creado por la Comunidad KDE se incluye siempre las fechas de las mismas siguiendo una especie de serie de Fibonacci.
La Comunidad KDE ha publicado la quinta actualización de Plasma 6.4, una versión que viene a subsanar los errores más graves de esta nueva versión del escritorio
Así que me congratula en presentar que hoy martes 11 de noviembre de 2025, casi cuatro meses después de liberar el código de Plasma 6.4 la Comunidad KDE presenta la sexta actualización de errores.

Más información: KDE
Las novedades generales de Plasma 6.4
Aprovecho para realizar un listado de las novedades generales de Plasma 6.4:
- Mejoras en el widget Bluetooth: Identifica más tipos de dispositivos y muestra nombres reales durante el emparejamiento.
- Coherencia visual: Los widgets de Diccionario y Navegador Web ahora usan iconos simbólicos para un aspecto más uniforme.
- Navegación mejorada por teclado: Optimización de la navegación y selección mediante teclado en menús y widgets.
- Modernización de KMenuEdit: Interfaz renovada y simplificada para editar el menú de aplicaciones.
- Mejoras en accesibilidad: El widget Calculadora anuncia resultados a lectores de pantalla y se mejora la navegación accesible.
- Gestión avanzada de paneles y monitores: Mejoras en la disposición y comportamiento de pantallas y paneles.
- Mejoras de rendimiento: Optimización de la suavidad del cursor y reducción del uso innecesario de CPU en el Monitor del Sistema.
- Mejoras en el widget Fifteen Puzzle: Se han realizado ajustes funcionales y visuales en este widget de juego clásico, ofreciendo una experiencia más fluida y atractiva.
- Actualización de Discover: El centro de software ahora muestra información más clara sobre el estado de las actualizaciones y mejora la gestión de aplicaciones Flatpak y Snap.
- Nuevas opciones en la configuración del sistema: Se han añadido controles más detallados para la personalización de temas y efectos visuales, facilitando la adaptación del entorno a las preferencias del usuario.
- Notificaciones mejoradas: El sistema de notificaciones es ahora más fiable y permite una mejor gestión de mensajes persistentes y temporales.
- Soporte ampliado para pantallas táctiles: Plasma 6.4 mejora la respuesta y precisión en dispositivos con pantalla táctil, optimizando gestos y controles táctiles.
- Optimización de Wayland: Se han corregido errores y mejorado la estabilidad y el rendimiento bajo el servidor gráfico Wayland, acercándolo a la paridad con X11.
- Mejoras en la gestión de energía: Nuevas opciones y mayor eficiencia en la gestión del consumo energético, especialmente en portátiles, para prolongar la autonomía y reducir el uso de recursos.
La entrada Sexta actualización de Plasma 6.4 se publicó primero en KDE Blog.
Episodio 57 de KDE Express: Cómo reportar un bug para que Albert lo arregle
Me congratula presentaros el episodio 57 de KDE Express, titulado «Cómo reportar un bug para que Albert lo arregle » donde David Marzal, y en esta ocasión con la ayuda de Albert Astals, de forma indirecta, sigue llevando en solitario estas más que interesantes píldoras. Un hurra por él… y por Albert. [Sí, Albert ya habló de ello pero es bueno recordarlo].
Episodio 57 de KDE Express: Cómo reportar un bug para que Albert lo arregle
Comenté hace ya bastante tiempo que había nacido KDE Express, un audio con noticias y la actualidad de la Comunidad KDE y del Software Libre con un formato breve (menos de 30 minutos) que complementan los que ya generaba la Comunidad de KDE España, aunque ahora estamos tomándonos un tiempo de respiro por diversos motivos, con sus ya veteranos Vídeo-Podcast que todavía podéis encontrar en Archive.org, Youtube, Ivoox, Spotify y Apple Podcast.
De esta forma, a lo largo de estos 45 episodios, promovidos principalmente por David Marzal, nos han contado un poco de todo: noticias, proyectos, eventos, etc., convirtiéndose (al menos para mi) uno de los podcast favoritos que me suelo encontrar en mi reproductor audio.
En palabras de David el nuevo episodio de KDE Express es un poco especial ya que sigue extrayendo valiosas píldoras de la última Akademy-es con un audio que empieza a ser un clásico:

Este episodio es el audio sacado de la charla que Albert dio en la AkademyES de este año Málaga. Podéis verlo en https://tube.kockatoo.org/w/ptTodio8pYeaRZdFdeKpPC o en una aplicación de podcast que soporte vídeo HLS como TrueFans o Fountain, pero nos ha parecido que su contenido es apropiado para poder escucharse solo. Como son cortas os dejamos en la descripción más abajo las notas de la presentación y aquí un enlace al PDF.
Ponente: Albert Astals Cid, Coordinador de traducciones de KDE
Malas prácticas
- No lo pongas solo en twitter/facebook/tiktok/mastodon
- No seas agresivo (SOIS UNOS PROGRAMADORES PESIMOS)
- No seas dramático (MI BUG ES EL BUG MÁS IMPORTANTE DEL MUNDO)
- No me «amenazes» (VOY A DEJAR DE USAR TU PROGRAMA)
- No me hagas trabajar de más
Buenas prácticas
- Usa el bug tracker correcto https://bugs.kde.org
- Si es un crash, que tenga símbolos
- Si es un error de funcionamiento, sé MUY PRECISO
- Si es un deseo piensalo dos vece
Y, como siempre, os dejo aquí el listado de los episodios. ¡Disfrutad!
Por cierto, también podéis encontrarlos en Telegram: https://t.me/KDEexpress
La entrada Episodio 57 de KDE Express: Cómo reportar un bug para que Albert lo arregle se publicó primero en KDE Blog.