checkinstall: The "chmod 777" Vulnerability You Didn't Ask For
Jan 15, 2026·5 min read
Executive Summary (TL;DR)
checkinstall 1.6.2 reads the permissions of a symlink (which technically appear as 777) and attempts to apply them to the file. Since `chmod` follows symlinks by default, it inadvertently sets the *target* binary to be world-writable. This allows any local user to overwrite root-owned executables packaged by the tool.
checkinstall 1.6.2, a tool beloved by sysadmins for creating quick-and-dirty packages, contains a critical flaw in how it handles symbolic links. By misinterpreting the nominal permissions of a symlink, it accidentally makes the target executable world-writable (0777). This turns a standard installation process into a Local Privilege Escalation (LPE) generator.
The Hook: The Lazy Admin's Best Friend
If you've managed Linux systems for more than a week, you've probably encountered the classic "make install" dilemma. You compile a tool from source, run sudo make install, and suddenly your filesystem is littered with binaries and libraries that you have no way to cleanly remove later. Enter checkinstall.
checkinstall is the hero we didn't deserve (and apparently, the one we shouldn't have trusted). It wraps the installation command, watches the filesystem calls to see what gets created, and magically spits out a .deb or .rpm that you can manage with your system's package manager. It's brilliant, convenient, and unfortunately, currently unmaintained.
But here's the catch: in its eagerness to be helpful and preserve file permissions exactly as they appear on the filesystem, checkinstall makes a catastrophic assumption about symbolic links. It assumes that what it sees is what it should set. And on Linux, what a symlink "looks like" is very different from what it actually is.
The Flaw: Symlinks are Liars
To understand this bug, you need to understand a quirk of Unix filesystems. If you run ls -l on a symbolic link, you'll almost always see permissions that look like this: lrwxrwxrwx. That's 777 in octal. It means "everyone can read, write, and execute this link."
However, these permissions are effectively a lie. The permissions of a symlink itself are largely irrelevant on Linux; the kernel ignores them and checks the permissions of the target file instead.
checkinstall missed this memo. During the packaging process, it iterates through the files it monitored. When it encounters a symlink, it queries its metadata. It sees 0777. It thinks, "Aha! This file is supposed to be world-writable! I better make sure the final package reflects that."
It then proceeds to run the equivalent of chmod 777 on that file. The problem? Unless you specifically tell it not to (e.g., chmod -h), chmod follows symbolic links. So, checkinstall isn't changing the link; it's following the link to the actual binary (say, /usr/bin/my-secure-app) and blasting its permissions wide open to the entire world.
The Logic Gap: A Visual Breakdown
The vulnerability exists in the logic flow between identifying files and finalizing the package structure. Here is how the catastrophe unfolds in the code logic:
This isn't a complex buffer overflow or a heap grooming exercise. It is a logic error born from a misunderstanding of how filesystem syscalls interact. The tool tries to be precise by copying permissions, but ends up being precisely wrong.
The Exploit: From Package to Pwnage
Exploiting this requires tricking an administrator into packaging a malicious layout, or simply waiting for them to package a legitimate tool that uses symlinks (which is... almost all of them).
Here is the attack path, derived from the Ubuntu bug report:
- Setup: We have a binary, let's call it
writable, which is safe (0755). - The Trap: We create a symlink named
vulnerablepointing towritable. - The Trigger: The admin runs
checkinstallto package this directory. - The Result:
checkinstallseesvulnerable(the symlink) has777perms. It applieschmod 777tovulnerable. The kernel applies this towritable.
If you inspect the resulting .deb file using dpkg -c, you will see:
-rwxrwxrwx root/root ... usr/bin/writable
Once installed, any user on the system can open /usr/bin/writable, delete its contents, and replace it with:
#!/bin/bash
cp /bin/bash /tmp/rootsh
chmod +s /tmp/rootshThe next time root runs that binary? Game over.
The Impact: Local Root for Everyone
The impact here is a straightforward Local Privilege Escalation (LPE). While it requires the victim (the admin) to perform an action (running checkinstall), the tool's entire purpose is to be run by admins with root privileges.
This is particularly dangerous in build pipelines or dev environments where checkinstall might be used to quickly generate artifacts for testing. If the source tree contains symlinks (very common for library versioning, e.g., lib.so -> lib.so.1), the resulting package will contain world-writable libraries.
A standard user doesn't even need to be clever. They just need to find a world-writable file in /usr/bin or /usr/lib, overwrite it with a reverse shell, and wait. It transforms the system into a playground where permissions are just a suggestion.
The Mitigation: Just Use FPM
The sad reality is that checkinstall is effectively abandonware. The upstream project is inactive, and while some distros maintain patches, the architectural flaws are deep.
Immediate Fixes:
- Stop using checkinstall. Seriously. It was great in 2010. It is now 2024.
- Verify your packages. If you must use it, never install the package blindly. Run
dpkg -c package.deband grep forrwxrwxrwx. If you see a binary with those permissions, burn it. - Use Modern Alternatives. The industry standard replacement is FPM (Effing Package Management). It is robust, actively maintained, and doesn't try to guess permissions based on symlinks in a way that destroys your security posture.
For those maintaining legacy systems: You can try to patch the checkinstall source to use lchmod or chmod -h (if supported) to avoid following links, or simply ignore permission setting for identified symlinks entirely.
Technical Appendix
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
checkinstall Canonical | = 1.6.2 | None |
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2020-25031 |
| CVSS v3.1 | 7.8 (High) |
| CWE | CWE-732 (Incorrect Permission Assignment) |
| Attack Vector | Local (User-assisted) |
| Impact | Privilege Escalation (LPE) |
| Affected Component | installwatch / checkinstall |
MITRE ATT&CK Mapping
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.