September 3, 2026
8 Linux Permissions That Quietly Become Security Risks
Your Linux server may be hardened, but are its permissions?

By bektiaw
10 min read
LINUX | CYBERSECURITY | CLOUD | SYSADMIN | DEVOPS
One bad permission can turn small mistakes into serious risks.
Permissions are probably the most boring part of Linux security. Nobody gets excited about auditing chmod bits. We'd rather talk about firewalls, SSH hardening, malware, intrusion detection, or zero-day vulnerabilities.
But here's the problem: a Linux server can be fully patched, protected by a firewall, hardened with strict SSH settings, and covered by layers of security controls, yet still be dangerously exposed.
- A file readable by everyone.
- A script writable by the wrong user.
- A sensitive directory with excessive access.
These look simple, but attackers can turn them into serious security problems. They can access sensitive files, modify trusted scripts, and even escalate privileges.
In this article, we'll look at the Linux permission mistakes that can quietly turn into real security risks, and how to find and fix them before an attacker does.
#1. SUID/SGID binaries nobody remembers adding
SUID and SGID let a program use the permissions of its owner or group instead of the permissions of the user running the program.
Some programs need extra access to do their job. Instead of giving the user running the program full access, SUID/SGID give the extra permission only to that program, making it safer and more controlled.
The problem starts when an unknown SUID/SGID binary appears that nobody remembers installing or configuring. If it is malicious or has a security flaw, an attacker may use its extra permissions to gain unauthorized access.
How to Fix It: Audit SUID/SGID Binaries
Regularly finding and comparing SUID/SGID binaries against a trusted baseline can help detect unexpected changes.
1. Find SUID/SGID binaries:
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f \
-exec ls -la {} \; 2>/dev/nullfind / -xdev \( -perm -4000 -o -perm -2000 \) -type f \
-exec ls -la {} \; 2>/dev/null2. Create a baseline:
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f \
2>/dev/null | sort > suid-baseline.txtfind / -xdev \( -perm -4000 -o -perm -2000 \) -type f \
2>/dev/null | sort > suid-baseline.txt- This baseline records the current SUID/SGID files on the system. Keep this baseline somewhere attackers cannot modify it.
3. Check for changes regularly (weekly or after installing/updating software)
diff suid-baseline.txt \
<(find / -xdev \( -perm -4000 -o -perm -2000 \) -type f \
2>/dev/null | sort)diff suid-baseline.txt \
<(find / -xdev \( -perm -4000 -o -perm -2000 \) -type f \
2>/dev/null | sort)- If
diffreturns nothing β The current list matches the baseline. - If
diffshows a new binary β Find out who installed it, which package owns it, when it appeared, and why it needs elevated privileges.
#2. World-Writable Files and Directories Anyone Can Modify
World-writable files and directories are files or folders that any user on the system can modify.
- World-writable file β Any user can change its contents.
- World-writable directory β Any user can create, delete, or modify files inside it (depending on permissions).
Some files or directories are intentionally shared between users, so they may be writable by everyone, such as /tmp, /var/tmp, /var/spool/, shared project directories, and some log or application directories.
However, world-writable files or directories can be a security risk if they contain sensitive data or are used by privileged programs, because any user may be able to modify them.
-rwxrwxrwx 1 root root 1842 Aug 18 09:20 backup.sh-rwxrwxrwx 1 root root 1842 Aug 18 09:20 backup.sh- That final
wmeans any user can modify the file. If it runs as root, they could change it to execute commands as root.
How to Fix It: Audit World-Writable Files
1. Find world-writable files and world-writable directories:
# Find world-writable files
find / -xdev -type f -perm -002 2>/dev/null
# Find world-writable directories without the sticky bit
find / -xdev -type d -perm -002 ! -perm -1000 2>/dev/null# Find world-writable files
find / -xdev -type f -perm -002 2>/dev/null
# Find world-writable directories without the sticky bit
find / -xdev -type d -perm -002 ! -perm -1000 2>/dev/null2. Investigate every unexpected result.
- Does this file really need to be writable by everyone?
- Is it a temporary or shared location?
- Is it executed by a privileged process?
- Can a low-privileged user modify it?
- Can the permission be restricted without breaking the application?
3. Fix the permissions
For a file that should not be world-writable:
# Remove write permission for other users
chmod o-w /path/to/file# Remove write permission for other users
chmod o-w /path/to/fileFor a world-writable directory that should not be:
# Remove write permission for other users
chmod o-w /path/to/directory# Remove write permission for other users
chmod o-w /path/to/directoryFor /tmp and /var/tmp, check that the sticky bit is enabled instead:
stat -c '%a %n' /tmp /var/tmp
# Expected: 1777
# Add the sticky bit if not enabled
chmod +t /tmp
chmod +t /var/tmpstat -c '%a %n' /tmp /var/tmp
# Expected: 1777
# Add the sticky bit if not enabled
chmod +t /tmp
chmod +t /var/tmp- Without the sticky bit, any user who can write to the directory may be able to delete or rename files owned by other users, not just create new files.
Important: Don't blindly remove permissions from every result. Check each file or directory first because some world-writable locations are required for normal system operation.
4. Check again
# Find world-writable files
find / -xdev -type f -perm -002 2>/dev/null
# Find world-writable directories without the sticky bit
find / -xdev -type d -perm -002 ! -perm -1000 2>/dev/null# Find world-writable files
find / -xdev -type f -perm -002 2>/dev/null
# Find world-writable directories without the sticky bit
find / -xdev -type d -perm -002 ! -perm -1000 2>/dev/nullBe careful with shared directories. Removing permissions blindly can break applications. The goal isn't to make everything read-only but to make sure only the users who actually need write access have it.
#3. /etc/shadow and Friends With the Wrong Mode
Some Linux files should not be readable by ordinary users because they contain sensitive information, such as passwords, private keys, or system configuration details.
/etc/passwdβ contains user account information. It is normally readable by all users, so it is not a secret file./etc/shadowβ contains password hashes and password-related information. It should normally be readable only by root (or a tightly controlled privileged group)./etc/groupβ contains group information and is normally readable by all users./etc/gshadowβ contains protected group password information and should be restricted./etc/security/*β Contains security-related configuration. Permissions depend on the specific file. Some may contain sensitive settings and should not be broadly readable.- application-specific credential files and configuration files β may contain passwords, API keys, tokens, or other sensitive information. Their permissions should be restricted to users or services that need access.
If those files become readable by an unprivileged user, an attacker who already has local access may be able to obtain passwords, private keys, or other sensitive information and use them to access protected accounts or systems.
How to Fix It: Audit Sensitive Authentication Files
1. Check the current ownership and permissions:
stat -c '%A %a %U:%G %n' \
/etc/passwd /etc/shadow /etc/group /etc/gshadowstat -c '%A %a %U:%G %n' \
/etc/passwd /etc/shadow /etc/group /etc/gshadow- Investigate
/etc/shadowand/etc/gshadowβ640or600, owned byroot:shadoworroot:root, depending on the distro./etc/passwdand/etc/groupβ usually644, owned byroot:root, and world-readable by design.
Note: Always verify the expected permissions for your specific Linux distribution before changing them.
3. Fix incorrect permissions
# For example, if /etc/shadow is accidentally world-readable:
chmod 640 /etc/shadow # Set restricted permissions
chown root:shadow /etc/shadow # Set the correct owner and group# For example, if /etc/shadow is accidentally world-readable:
chmod 640 /etc/shadow # Set restricted permissions
chown root:shadow /etc/shadow # Set the correct owner and groupLinux Permissions: Users, Groups, ACLs, and Sudo for Security Learn Linux users, groups, and ACLs to control access, enforce privilege boundaries, and keep our system safe fromβ¦
4. Verify
stat -c '%A %a %U:%G %n' \
/etc/passwd /etc/shadow /etc/group /etc/gshadowstat -c '%A %a %U:%G %n' \
/etc/passwd /etc/shadow /etc/group /etc/gshadowConfirms that the permissions and ownership are correct after making changes.
Sensitive authentication files should only be readable or writable by the accounts that actually need access.
#4. SSH key and .ssh directory permissions
SSH keys are often considered more secure than passwords. This is only true if the private key and SSH configuration files are properly protected.
A private key that is readable by another user can be copied and potentially used to log in as that account.
Private keys aren't the only concern. An overly permissive authorized_keys file can allow another local user to modify which public keys are trusted for SSH access.
How to Fix It: Audit SSH Permissions
1. Find SSH keys and configuration files
find /home /root -type f \
\( -name "id_*" -o -name "authorized_keys" -o -name "config" \) \
-ls 2>/dev/nullfind /home /root -type f \
\( -name "id_*" -o -name "authorized_keys" -o -name "config" \) \
-ls 2>/dev/nullid_*β SSH key files, including private and public keysauthorized_keysβ keys allowed to authenticate to the accountconfigβ per-user SSH client configuration
2. Check permissions and ownership
stat -c '%A %a %U:%G %n' /path/to/.ssh /path/to/private_key /path/to/authorized_keysstat -c '%A %a %U:%G %n' /path/to/.ssh /path/to/private_key /path/to/authorized_keys- Private keys β usually
600and owned by the account using them. authorized_keysβ usually600and owned by the account receiving SSH access..sshdirectory β usually700and owned by the account using it.
3. Fix incorrect permissions
For private keys:
# Only the owner can read and write the private key
chmod 600 /path/to/private_key# Only the owner can read and write the private key
chmod 600 /path/to/private_keyFor authorized_keys:
# Only the owner can read and modify trusted SSH keys
chmod 600 /path/to/authorized_keys# Only the owner can read and modify trusted SSH keys
chmod 600 /path/to/authorized_keysFor the .ssh directory:
# Only the owner can access the SSH directory
chmod 700 /path/to/.ssh# Only the owner can access the SSH directory
chmod 700 /path/to/.ssh4. Remove unnecessary keys
Permissions alone aren't enough. Review authorized_keys and remove public keys that are no longer needed.
# Review and remove keys that should no longer have SSH access
nano ~/.ssh/authorized_keys# Review and remove keys that should no longer have SSH access
nano ~/.ssh/authorized_keys5. Verify again
# Confirm the permissions and ownership are correct
stat -c '%A %a %U:%G %n' /path/to/.ssh /path/to/private_key /path/to/authorized_keys# Confirm the permissions and ownership are correct
stat -c '%A %a %U:%G %n' /path/to/.ssh /path/to/private_key /path/to/authorized_keysPrivate keys should stay private, authorized_keys should not be writable by untrusted users, and every SSH key should have a reason to exist.
#5. Sudoers Entries Wider Than They Need to Be
sudo is designed to let users run specific commands with elevated privileges without giving them full root access.
The danger is when the sudoers configuration grants more access than the user actually needs.
user ALL=(ALL) NOPASSWD: ALLβ gives the user unrestricted root access without a password.- Wildcard command paths β rules like
user ALL=(root) /usr/bin/systemctl *may allow more actions than intended. - Shells, editors, and interpreters β allowing tools such as
vim,less,python3, orawkthroughsudocan let users run commands with elevated privileges.
How to Fix It: Audit Sudoers Entries
1. Check the sudoers syntax
sudo visudo -csudo visudo -c- This verifies that the sudoers configuration is syntactically valid before we make or review changes.
2. Look for potentially broad rules
grep -rP '(NOPASSWD|ALL)' /etc/sudoers /etc/sudoers.d/ 2>/dev/nullgrep -rP '(NOPASSWD|ALL)' /etc/sudoers /etc/sudoers.d/ 2>/dev/null- Review every match, especially entries containing:
NOPASSWD: ALL,(ALL) ALL. These can grant much more privilege than intended.
3. Fix risky sudoers entries
# Edit and remove unnecessary or overly broad permissions
sudo visudo
# For a file in /etc/sudoers.d/
sudo visudo -f /etc/sudoers.d/filename
# Edit and remove unnecessary or overly broad permissions
sudo visudo
# For a file in /etc/sudoers.d/
sudo visudo -f /etc/sudoers.d/filename
After making changes, verify the configuration:
# Confirm the sudoers syntax is valid
sudo visudo -c# Confirm the sudoers syntax is valid
sudo visudo -cLeast privilege is the goal. Be careful with programs that can execute arbitrary commands or open another shell when run with elevated privileges.
vim
less
more
man
find
awk
perl
python
ruby
bash
shvim
less
more
man
find
awk
perl
python
ruby
bash
sh#6. Cron jobs and systemd units writing into user-writable paths
Scheduled tasks are another place where bad permissions can quietly become a privilege escalation path.
Cron jobs and systemd units can become a security risk when they run scripts or programs that ordinary users can modify.
Linux Cron Jobs: How to Automate Tasks Like a Pro DevOps Engineer LINUX | SERVER | UBUNTU | CLOUD | SERVER | DEVOPS Linux Cron Jobs: How to Automate Tasks Like a Pro DevOps Engineerβ¦
Systemd Timers: Modern Task Scheduling (Better than Cron?) Time to Move Beyond Cron
How to Fix It: Audit Scheduled Tasks
Cron Jobs:
1. Find scheduled jobs
crontab -l -u root # List root's scheduled cron jobs
cat /etc/crontab /etc/cron.d/* 2>/dev/null # Check system-wide cron jobscrontab -l -u root # List root's scheduled cron jobs
cat /etc/crontab /etc/cron.d/* 2>/dev/null # Check system-wide cron jobs2. Check the scripts they run
# Check who owns the script and who can modify it
ls -la /path/to/script# Check who owns the script and who can modify it
ls -la /path/to/scriptIf a root cron job runs a script that a normal user can modify, they could change the script and run commands as root when the cron job runs.
Systemd Units:
1. Find systemd timers
systemctl list-timers --allsystemctl list-timers --all2. Check service files for weak permissions
# Find service files that are writable by group or other users
find /etc/systemd/system /usr/lib/systemd/system \
-type f -name '*.service' -perm -022 2>/dev/null# Find service files that are writable by group or other users
find /etc/systemd/system /usr/lib/systemd/system \
-type f -name '*.service' -perm -022 2>/dev/null3. Check what commands services execute
# Show the commands that systemd services run
grep -H '^ExecStart' /etc/systemd/system/*.service 2>/dev/null# Show the commands that systemd services run
grep -H '^ExecStart' /etc/systemd/system/*.service 2>/dev/nullA systemd service is risky if its unit file or ExecStart program can be modified by an unprivileged user. The modified program could then run with the service's privileges, often root.
#7. Capabilities as a Silent SUID Replacement
SUID isn't the only way a Linux program can gain extra privileges.
Linux capabilities give programs specific privileges without giving them full root access. This can be safer than SUID, but a capability that gives a program more access than it needs can still be dangerous.
How to Fix It: Audit Linux Capabilities
1. Find binaries with capabilities
getcap -r / 2>/dev/null
# List files that have Linux capabilitiesgetcap -r / 2>/dev/null
# List files that have Linux capabilities2. Review the results
Pay close attention to powerful capabilities such as:
cap_setuidβ can change the process user ID.cap_sys_adminβ provides a wide range of powerful system privileges.
Investigate any capability that is unexpected or not required by the program.
3. Remove unnecessary capabilities
# Remove an unnecessary capability
sudo setcap -cap_setuid /path/to/binary
# To remove all capabilities from a binary
sudo setcap -r /path/to/binary# Remove an unnecessary capability
sudo setcap -cap_setuid /path/to/binary
# To remove all capabilities from a binary
sudo setcap -r /path/to/binary4. Verify
getcap /path/to/binary
# Confirm the unwanted capability is gonegetcap /path/to/binary
# Confirm the unwanted capability is gone5. Baseline the system
# Save the current capability list for later comparison
getcap -r / 2>/dev/null | sort > capabilities-baseline.txt
# Save the current capability list for later comparison
getcap -r / 2>/dev/null | sort > capabilities-baseline.txt
6. Compare the current list with the baseline
Run this regularly, such as weekly, and after major software installations or updates:
# Show new or changed capabilities
diff capabilities-baseline.txt <(getcap -r / 2>/dev/null | sort)# Show new or changed capabilities
diff capabilities-baseline.txt <(getcap -r / 2>/dev/null | sort)Investigate any new or unexpected capabilities before updating the baseline.
#8. Docker Socket and Container-Adjacent Permissions
The Docker socket is a special file that allows programs and containers to communicate with the Docker daemon. It is usually located at /var/run/docker.sock.
Docker socket can be accessed by root and users in the docker group. It can also be exposed to a container by mounting the host socket:
docker run -v /var/run/docker.sock:/var/run/docker.sock IMAGEdocker run -v /var/run/docker.sock:/var/run/docker.sock IMAGEThe Docker socket is highly privileged. Anyone who can access /var/run/docker.sock may effectively have root-level control over the host.
If an untrusted user or container can communicate with the Docker socket, they may be able to create containers with powerful host access, mount sensitive host paths, or otherwise use Docker's privileges to affect the host.
How to Fix It: Audit Docker Permissions
1. Check Docker socket permissions
# Check the socket owner, group, and permissions
ls -l /var/run/docker.sock
# A typical setup:
srw-rw---- 1 root docker ... /var/run/docker.sock# Check the socket owner, group, and permissions
ls -l /var/run/docker.sock
# A typical setup:
srw-rw---- 1 root docker ... /var/run/docker.sock- Check who is in the
dockergroup
# List users who have access to the Docker socket
getent group docker# List users who have access to the Docker socket
getent group docker3. Check which containers have the socket mounted
docker ps --format '{{.Names}}' | while read c; do
docker inspect -f '{{.Name}}: {{range .Mounts}}{{if eq .Source "/var/run/docker.sock"}}Docker socket mounted{{end}}{{end}}' "$c"
donedocker ps --format '{{.Names}}' | while read c; do
docker inspect -f '{{.Name}}: {{range .Mounts}}{{if eq .Source "/var/run/docker.sock"}}Docker socket mounted{{end}}{{end}}' "$c"
done4. Remove unnecessary Docker group access
# Remove a user from the docker group
sudo gpasswd -d username docker# Remove a user from the docker group
sudo gpasswd -d username docker5. Review containers with Docker socket access
If a container does not need Docker daemon access, remove the socket mount from its configuration and recreate the container.
6. Verify
# Confirm that only required users have access
getent group docker
ls -l /var/run/docker.sock# Confirm that only required users have access
getent group docker
ls -l /var/run/docker.sockFinal Thoughts
Linux permissions are about controlling who can access, modify, or run them. The goal is least privilege: give users and programs only the permissions they need.
Linux permissions are boring. No fancy tools, exploits, or zero-days. Just audit regularly, compare against a trusted baseline, and investigate unexpected changes. The key question is simple: Who can read, write, run, or change what?
Thanks for reading! Hope this article helps you spot the small Linux permission mistakes that can turn into big security problems.