← Back to Blog

Linux GUI Security: Achieving 100/100

Linux GUI Security: Achieving 100/100 - QNSQY post-quantum encryption guide

Why Securing a GUI Application Is Hard

A command-line program is relatively simple to lock down. It reads input, processes it, writes output, and exits. It does not need to draw windows, handle mouse clicks, or talk to a display server. A post-quantum cryptography tool running in a terminal can have the Linux kernel block every network connection, restrict file access to exactly the files the user specified, and prevent any other program from reading its memory. The CLI version of QNSQY does all of this.

A GUI application is a completely different challenge. To draw a window on your screen, the application must communicate with your display server (the system component responsible for rendering graphics). On most Linux systems, this is either X11 or Wayland. That communication happens through sockets, which look like network connections to the kernel. If you block all sockets, the GUI cannot draw anything. If you allow sockets, you open a communication channel that potentially exposes the application to other programs on the system.

Think of it this way: a CLI program is like a worker in a sealed, windowless room. They receive documents through a slot in the door, process them, and slide the results back out. Nobody can see what they are doing. A GUI program is like a worker in a glass-walled office. They are still doing the same job, but now everyone walking by can look through the windows. The challenge is making those glass walls as secure as possible.

QNSQY's Linux GUI tackles this with multiple layers of protection: Wayland isolation, Landlock filesystem sandboxing, Slint UI framework (which avoids web technologies), kernel-protected memory, and compilation hardening. Each layer compensates for potential weaknesses in the others. This is the principle of defense in depth, recommended by security frameworks like NIST SP 800-53.

The X11 Problem: Why the Old Display Server Is Dangerous

X11, also called the X Window System, has been the standard Linux display server since 1987. It was designed in an era when all users on a system were trusted. As a result, X11 has no isolation between applications. Any application running under X11 can:

  • Record every keystroke typed into any other application. If you type a password into QNSQY, a malicious app running in the background can see every character.
  • Take screenshots of any window, including windows belonging to other applications. Your decrypted document, visible on screen, can be captured silently.
  • Inject fake keyboard and mouse input into other applications. A malicious program could type commands into your terminal as if you were typing them yourself.

This is not a theoretical vulnerability. Real-world keyloggers for Linux commonly exploit X11's open architecture. The xinput tool, shipped with most Linux distributions, can log every keystroke on the system with a single command. It is not a hack; it is a feature of X11's design.

For a cryptography tool, this is catastrophic. The entire security model depends on your password being secret. If any other application can read your password as you type it, encryption becomes meaningless.

Wayland: Isolation by Design

Wayland is the modern replacement for X11. It was designed from scratch with application isolation as a core principle. Under Wayland:

  • Each application can only see its own input. When you type your password into QNSQY, no other application receives those keystrokes. The Wayland compositor (the program managing the display, such as GNOME's Mutter or KDE's KWin) delivers input events only to the window that has focus.
  • Each application can only see its own windows. Applications cannot capture screenshots of other applications' windows. The only way to take a screenshot under Wayland is through a compositor-controlled portal that requires explicit user permission.
  • Applications cannot inject input into other applications. There is no equivalent of X11's XSendEvent or XTest extensions. One application cannot pretend to type into another.

QNSQY's GUI uses the Slint UI framework, which renders directly through Wayland without using a web browser engine, Electron, or GTK/Qt intermediate layers. This reduces the attack surface because there is no embedded browser that could be exploited via web vulnerabilities, and no large widget toolkit with its own history of security bugs.

Major Linux distributions have switched to Wayland as the default: Fedora (since Fedora 25), Ubuntu (since 21.04), and GNOME and KDE both default to Wayland sessions. If you are still using X11, consider switching. You can check which display server you are using by running:

echo $XDG_SESSION_TYPE

This will print either wayland or x11.

Landlock: Filesystem Sandboxing

Landlock is a Linux security module (available since kernel 5.13) that lets applications restrict their own filesystem access. Think of it as a program voluntarily giving up permissions it does not need.

A normal application can read and write any file that the user running it can access. If you run a program as your regular user account, that program can read your documents, your browser history, your SSH keys, and anything else owned by your user. If the application has a vulnerability, an attacker who exploits it gains access to all those files.

Landlock changes this. When QNSQY's GUI starts, it tells the kernel: "I only need access to these specific files and directories. Block me from accessing anything else." After that, even if the application has a vulnerability, the attacker is trapped inside the sandbox, unable to reach your other files.

Specifically, QNSQY's Landlock policy allows:

  • Read access to the file you selected for encryption/decryption
  • Write access to the output directory
  • Read access to QNSQY's own configuration files
  • No access to anything else: not your home directory, not your SSH keys, not your browser profile, not /etc, nothing

The Landlock documentation in the Linux kernel source describes it as a "security sandboxing" mechanism that does not require root privileges. Any unprivileged process can use it, making it practical for end-user applications.

CLI vs GUI: Understanding the Security Tradeoff

The QNSQY CLI on Linux uses seccomp-bpf (Secure Computing mode with Berkeley Packet Filter) to block network system calls at the kernel level. When the CLI is running, the Linux kernel will kill the entire process if it attempts to make any network connection. This is enforced by the kernel, not by the application itself. Even if an attacker gains full control of the QNSQY process, they cannot make a network connection because the kernel refuses to execute the system call.

The GUI cannot do this. Drawing a window requires communicating with the Wayland compositor through a Unix socket, and Unix sockets use the same system calls as network sockets (socket(), connect(), sendmsg()). If seccomp blocks these calls, the GUI cannot display anything.

This means the GUI has a fundamentally wider attack surface than the CLI. The CLI can operate in a fully air-gapped mode where the kernel guarantees no network communication. The GUI cannot make this guarantee because it needs sockets to function.

Here is a direct comparison:

Security Feature CLI GUI
Network blocking (seccomp) All network syscalls blocked by kernel Cannot block (needs display sockets)
Filesystem sandboxing Landlock (input/output files only) Landlock (input/output files only)
Memory protection mlock + memfd_secret + zeroize mlock + memfd_secret + zeroize
Display isolation Not applicable (no display) Wayland compositor isolation
Core dump prevention RLIMIT_CORE = 0 RLIMIT_CORE = 0

The practical recommendation: for maximum security, use the CLI. For convenience with strong security, use the GUI on Wayland. If you are handling classified material, government data, or anything where "strong" is not good enough and you need "absolute," the CLI is the right choice.

memfd_secret: Kernel-Protected Memory

When you type your encryption password, that password exists in memory for a brief time while QNSQY processes it. On a normal Linux system, this memory can potentially be read by:

  • The root user, via /proc/[pid]/mem
  • A debugger attached to the process
  • Memory forensics tools examining a core dump or raw RAM
  • In some configurations, even the kernel itself when servicing a page fault

Linux kernel 5.14 introduced the memfd_secret() system call. It creates a region of memory with extraordinary protection:

  • Invisible to other processes, including processes running as root. Reading /proc/[pid]/mem for those pages returns zeros.
  • Excluded from core dumps. If the application crashes, the password is not included in the crash dump.
  • Unmapped from kernel direct-mapping (when the kernel supports it). This means even the kernel cannot casually access the data during normal operation.

QNSQY stores passwords and derived encryption keys in memfd_secret memory. When the operation completes, the memory is explicitly zeroed before being released. This combination means the password exists in protected memory for the shortest possible time and is scrubbed when no longer needed.

Secure Attention Sequence: Verifying the Password Prompt

A sophisticated attacker could create a fake QNSQY window that looks identical to the real one, display it when you are about to type your password, and steal whatever you type. This is the GUI equivalent of a phishing attack: instead of a fake website, it is a fake application window.

QNSQY defends against this with a Secure Attention Sequence (SAS), the same concept used by Windows' Ctrl+Alt+Delete. Before the password field becomes active:

  1. You press Ctrl+Alt+S
  2. The Wayland compositor verifies that this key combination came from actual physical keyboard hardware, not from another application simulating key presses
  3. Only after this verification does the password field become editable

A fake window cannot intercept or simulate this key combination under Wayland because applications cannot inject input into other applications. If the SAS check fails, the password field stays disabled, alerting you that something is wrong.

Flatpak Sandboxing

QNSQY's GUI is distributed as a Flatpak package for Linux. Flatpak provides application-level sandboxing with tight permission control:

  • No network access. The Flatpak manifest specifies no network permission. The application cannot make any outbound connections.
  • Limited filesystem access. The app can only see files that you explicitly open through the file picker portal. It cannot browse your home directory.
  • D-Bus filtering. Communication with other applications via the D-Bus message bus is restricted to approved portals only.
  • Seccomp profile. The Flatpak runtime applies a seccomp profile that blocks dangerous system calls.

These restrictions apply even if an attacker somehow gains code execution inside the QNSQY process. The sandbox limits what they can do to the narrow set of permissions the application declared at install time.

Compilation Hardening

Beyond runtime sandboxing, QNSQY is compiled with multiple security hardening flags that make exploitation more difficult even if a vulnerability exists:

  • ASLR and PIE (Position Independent Executable): The operating system loads the program at a random memory address every time it runs. An attacker trying to exploit a memory corruption bug needs to know where the program is loaded in memory, and ASLR makes this unpredictable.
  • Stack canaries: The compiler inserts random "canary" values on the stack before function return addresses. If a buffer overflow overwrites the return address, it will also overwrite the canary. The program detects the corrupted canary and terminates before the attacker gains control.
  • FORTIFY_SOURCE=2: The compiler replaces standard C library functions (like memcpy and sprintf) with safer versions that check buffer sizes at runtime. If a copy would overflow its destination, the program aborts instead of letting the overflow occur.
  • Zeroization: All passwords, keys, and sensitive data are overwritten with zeros immediately after use. QNSQY uses the zeroize crate in Rust, which is specifically designed to prevent the compiler from optimizing away the zeroing operation (a common problem where the compiler removes "unnecessary" writes to memory that is about to be freed).

When to Use GUI vs CLI

Both the GUI and CLI are secure, but they serve different purposes:

  • Use the GUI when you want a visual interface for occasional data encryption, when you are not comfortable with terminal commands, or when you need to quickly encrypt/decrypt a few files during your normal desktop workflow.
  • Use the CLI when you need maximum security guarantees (kernel-level network blocking), when you are automating encryption in scripts, when you are working on an air-gapped machine, or when you are handling classified or highly sensitive data.

Internally, the GUI actually spawns the CLI as a subprocess for all cryptographic operations. The GUI handles the user interface; the CLI does the actual encryption. This means the crypto code gets the CLI's security protections (seccomp, Landlock) even when you are using the GUI.

The Threat Model

Understanding what each mode protects against helps you make the right choice:

  • Malware on your system: Both GUI and CLI protect against malware reading your data from disk (it is encrypted). The CLI additionally prevents the encryption process from communicating with the internet, so malware injected into the QNSQY process cannot exfiltrate data. The GUI protects against other GUI applications spying via Wayland isolation.
  • Physical access to your computer: Both protect equally. Encrypted files on disk require the password to decrypt.
  • Memory forensics: Both use mlock (preventing swap to disk) and zeroization. The GUI additionally uses memfd_secret for kernel-level memory protection.
  • Supply chain attacks: Both verify binary integrity at startup with a self-hash check. If the binary has been modified, QNSQY refuses to run.

Why Slint Instead of Electron or GTK

Many desktop applications today use Electron, which embeds an entire Chromium web browser inside the application. This approach is convenient for developers but carries significant security implications. Chromium is millions of lines of C++ code with a large attack surface. Browser engines are a frequent target for exploits because they parse untrusted content (HTML, CSS, JavaScript, images, fonts) by design. Embedding a browser engine inside an encryption application means that the encryption application inherits all of those parsing vulnerabilities.

QNSQY uses Slint, a native UI toolkit written in Rust. Slint renders directly to the screen using GPU-accelerated graphics, without any embedded browser, HTML parser, or JavaScript engine. The UI code compiles to native machine code, eliminating the class of vulnerabilities that come from interpreting web content. There is no DOM, no CSS parser, and no JavaScript runtime for an attacker to target.

GTK and Qt are established native toolkits, but they are written primarily in C and C++, languages that do not have memory safety guarantees. Buffer overflows, use-after-free bugs, and other memory corruption vulnerabilities have been found in both toolkits over the years. Slint is written in Rust, which eliminates entire classes of memory safety bugs at compile time through its ownership and borrowing system.

Core Dump Prevention

When a program crashes, the operating system can write the program's entire memory to a "core dump" file. This file is useful for debugging, but for an encryption application, it is a disaster. A core dump could contain your password, your encryption keys, and the plaintext of files being processed.

QNSQY disables core dumps at startup by setting RLIMIT_CORE to zero using the setrlimit() system call. This instructs the kernel to never write a core dump for the process, regardless of how the process terminates. Even if QNSQY crashes due to a bug, no memory contents are written to disk.

Combined with mlock (which prevents memory from being written to swap space), this means that sensitive data only ever exists in RAM and is never written to persistent storage in an uncontrolled way.

Binary Integrity Verification

When QNSQY starts, it computes a BLAKE3 hash of its own executable file and compares it against an expected value. If the hash does not match, QNSQY refuses to run. This protects against tampering: if an attacker modifies the QNSQY binary (to add a backdoor, disable encryption, or exfiltrate keys), the hash check will fail and the modified binary will not execute any cryptographic operations.

This is not a perfect defense against sophisticated attackers (who could patch the hash check itself), but it raises the bar significantly. An attacker must understand the binary's internal structure well enough to modify both the functional code and the integrity check simultaneously, which is substantially harder than simply patching a function.

Sources

  1. Linux kernel Landlock documentation - https://docs.kernel.org/userspace-api/landlock.html
  2. Linux kernel seccomp documentation - https://docs.kernel.org/userspace-api/seccomp_filter.html
  3. memfd_secret(2) man page - https://man7.org/linux/man-pages/man2/memfd_secret.2.html
  4. Wayland protocol documentation - https://wayland.freedesktop.org/docs/html/
  5. NIST SP 800-53 Rev. 5: Security and Privacy Controls (defense in depth) - https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final

Related Articles

Maximum Security, Minimum Hassle

QNSQY's Linux GUI is the most secure encryption application available.

Try QNSQY

Originally published at quantumsequrity.com/blog/linux-gui-security.