CVE-2020-25031

checkinstall: The "chmod 777" Vulnerability You Didn't Ask For

Amit Schendel
Amit Schendel
Senior Security Researcher

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:

  1. Setup: We have a binary, let's call it writable, which is safe (0755).
  2. The Trap: We create a symlink named vulnerable pointing to writable.
  3. The Trigger: The admin runs checkinstall to package this directory.
  4. The Result: checkinstall sees vulnerable (the symlink) has 777 perms. It applies chmod 777 to vulnerable. The kernel applies this to writable.

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/rootsh

The 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:

  1. Stop using checkinstall. Seriously. It was great in 2010. It is now 2024.
  2. Verify your packages. If you must use it, never install the package blindly. Run dpkg -c package.deb and grep for rwxrwxrwx. If you see a binary with those permissions, burn it.
  3. 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 Score
7.8/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Affected Systems

Linux systems using checkinstall 1.6.2 for package managementDebian-based distributions (Ubuntu, Kali, etc.)RPM-based distributions using the tool

Affected Versions Detail

Product
Affected Versions
Fixed Version
checkinstall
Canonical
= 1.6.2None
AttributeDetail
CVE IDCVE-2020-25031
CVSS v3.17.8 (High)
CWECWE-732 (Incorrect Permission Assignment)
Attack VectorLocal (User-assisted)
ImpactPrivilege Escalation (LPE)
Affected Componentinstallwatch / checkinstall
CWE-732
Incorrect Permission Assignment for Critical Resource

Vulnerability Timeline

Vulnerability reported to Ubuntu by Gianni Tedesco
2020-01-29
Debian acknowledges bug, notes upstream is dead
2020-02-05
CVE-2020-25031 Published
2020-08-31

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.