Ever created a script in Linux, only to realize it’s world-readable when it contains sensitive credentials? Or worse—discovered that your automated backup files have been exposed to every user on the system?
That’s where umask comes in. This little command is your first line of defense against permission nightmares.
In this guide, I’ll show you exactly how to use the umask command in Linux to control default file permissions. We’ll cover everything from basic concepts to real-world security scenarios I’ve encountered in production environments.
What is the umask Command in Linux?
The umask command is a shell builtin that sets default permissions for newly created files and directories. Think of it as a permission template that automatically applies every time you create a new file.
When you run touch newfile.txt or mkdir newdir, Linux doesn’t just randomly assign permissions. Your current umask value determines what permissions those new files get.

Understanding File Creation Masks
Here’s the key concept: umask is a mask that removes permissions, not one that sets them directly.
Linux starts with base permissions:
- 666 (rw-rw-rw-) for files
- 777 (rwxrwxrwx) for directories
Your umask then subtracts from these base permissions. If your umask is 022, the calculation works like this:
- Files: 666 – 022 = 644 (rw-r–r–)
- Directories: 777 – 022 = 755 (rwxr-xr-x)
This filtering mechanism ensures consistent, secure defaults across your entire system.
umask vs chmod: What’s the Difference?
I get asked this constantly, so let’s clear it up once and for all.
The umask sets default permissions for new files. It’s proactive. The chmod command changes permissions on existing files. It’s reactive.
Think of umask as a template you configure once, and chmod as a tool you use to fix individual files that need different permissions.
Here’s a practical example:
$ umask 077 # Set restrictive default $ touch secret.txt # New file created with 600 permissions $ chmod 644 old.txt # Change existing file permissions
The umask ensured secret.txt was private from creation. The chmod fixed an existing file.
Why umask Matters for Security
Here’s the truth: most security breaches I’ve seen in multi-user environments trace back to overly permissive default permissions.
When your umask is too loose (like 000), every file you create is world-readable and world-writable. That database backup script you just wrote? Everyone can read your credentials. That log file your web server generates? Anyone can see user activity.
Critical scenarios where umask matters:
- Multi-user systems: Prevent users from reading each other’s files
- Web servers: Stop world-readable logs from leaking sensitive data
- DevOps pipelines: Ensure CI/CD artifacts don’t expose secrets
- Compliance: Meet security standards like CIS Security Benchmarks
- Database backups: Keep backup files private by default
The CIS Security Benchmarks specifically recommend a umask of 027 for system accounts in security-conscious environments. That’s not arbitrary—it’s based on years of breach analysis.
How to Check Your Current umask Value
Before changing anything, you need to know your current setting. It’s a one-liner.
Viewing umask in Octal Notation
Just type umask with no arguments:
$ umask 0022
That leading zero is the special permissions bit (setuid/setgid/sticky). For most purposes, focus on the last three digits: 022.
Common default values you’ll encounter:
- 0022 – Standard for most Linux distributions (files: 644, directories: 755)
- 0002 – Common in collaborative environments (files: 664, directories: 775)
Viewing umask in Symbolic Mode
Prefer human-readable output? Use the -S flag:
$ umask -S u=rwx,g=rx,o=rx
This shows the permissions that will be set on new directories. It’s the inverse of the mask itself—which I find way more intuitive for beginners.
Understanding umask Octal Notation
Let’s break down the math behind umask values. This is where it clicks for most people.
How umask Calculation Works
Each digit in octal notation represents a permission set:
| Position | Applies To | Example (022) |
|---|---|---|
| 1st digit | User/Owner | 0 (no permissions removed) |
| 2nd digit | Group | 2 (write removed) |
| 3rd digit | Others | 2 (write removed) |
Each octal digit breaks down further:
- 4 = read (r)
- 2 = write (w)
- 1 = execute (x)
So a umask of 022 removes write permission (2) from group and others, leaving the owner with full permissions.
Common umask Values Explained
Here are the values I use most often and when:
| umask | File Perms | Dir Perms | Use Case |
|---|---|---|---|
| 022 | 644 (rw-r–r–) | 755 (rwxr-xr-x) | Standard workstation, general use |
| 002 | 664 (rw-rw-r–) | 775 (rwxrwxr-x) | Shared development environments |
| 027 | 640 (rw-r—–) | 750 (rwxr-x—) | Security-focused servers, system accounts |
| 077 | 600 (rw——-) | 700 (rwx——) | Maximum security, private files only |
The 077 umask is what I use when generating SSH keys or handling sensitive credentials—completely private from creation.
Setting umask Temporarily
Want to test a different umask without committing? Just set it for your current shell session.
$ umask 077 $ touch testfile.txt $ ls -l testfile.txt -rw------- 1 alex alex 0 Sep 15 10:32 testfile.txt
See that? The file was created with 600 permissions (owner read/write only) because we set umask to 077.
This is perfect for one-off secure operations:
# Temporarily use restrictive umask for backup $ umask 077 $ mysqldump -u root -p database > backup.sql $ ls -l backup.sql -rw------- 1 alex alex 2048576 Sep 15 10:35 backup.sql
Once you close that terminal or logout, your umask reverts to whatever’s configured in your profile.
Making umask Permanent for Your User
Temporary changes are great for testing, but you’ll want to make your preferred umask stick.
Adding umask to .bashrc
For Bash users (the most common Linux shell), edit your ~/.bashrc:
$ echo "umask 027" >> ~/.bashrc $ source ~/.bashrc
Now every new interactive shell will use your custom umask. Verify it worked:
$ umask 0027
Perfect. From now on, new files get created with 640 permissions (rw-r—–) automatically.
Adding umask to .bash_profile or .profile
Here’s a nuance that catches people: .bashrc runs for interactive non-login shells, while .bash_profile (or .profile) runs for login shells.
For maximum coverage, I usually put umask in both:
# In ~/.bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
umask 027This ensures your umask applies whether you SSH in (login shell) or open a terminal window (non-login shell).
If you’re modifying config files programmatically, you might use sed for text processing to inject the umask line.
Setting umask System-Wide
Need to enforce a umask for all users on a system? You’ve got options.
Modifying /etc/profile
The traditional approach is editing /etc/profile:
$ sudo nano /etc/profile
Add near the top:
# Set default umask for all users umask 027
This affects all users at login, but it can be overridden by individual user profiles.
Using /etc/profile.d/ for Custom Scripts
I prefer the modular approach—create a dedicated script:
$ sudo nano /etc/profile.d/umask.sh
Content:
#!/bin/bash # System-wide umask setting umask 027
Make it executable:
$ sudo chmod +x /etc/profile.d/umask.sh
This keeps your custom configuration isolated and easy to manage. If you need to revert, just delete this one file instead of digging through /etc/profile.
Understanding /etc/login.defs
For systems using PAM (most modern Linux distributions), check /etc/login.defs:
$ grep UMASK /etc/login.defs UMASK 027
This sets the umask for login sessions. According to the umask man page, PAM modules can override this, so verify your actual effective umask after login.
The priority order is:
- PAM umask argument
- User GECOS field
/etc/login.defsUMASK- Shell profile files
Red Hat’s file permissions guide covers this in detail for enterprise environments.
Real-World umask Examples Every Admin Needs
Theory is great, but let me show you how I actually use umask in production.
Web Server Configuration Files
Web servers like Nginx and Apache create log files constantly. With a loose umask, those logs can expose sensitive data.
I set umask 027 in the web server’s systemd service file:
[Service] User=www-data Group=www-data UMask=0027 ExecStart=/usr/sbin/nginx
Now all logs created by Nginx have permissions 640 (rw-r—–). The www-data user can write, the group can read, and others get nothing. Perfect for security-hardened systems.
Shell Scripts and Automation
Here’s a mistake I see constantly: automation scripts that create files with inconsistent permissions.
Always set umask at the top of your scripts:
#!/bin/bash umask 077 # Ensure private file creation # Generate sensitive report echo "Secret data" > /var/reports/confidential-$(date +%Y%m%d).txt # File is automatically 600 (rw-------)
This is especially critical for scripts scheduled with cron, which might run with a different umask than your interactive shell.
Shared Development Environments
Got multiple developers working on the same server? Use umask 002 so group members can edit each other’s files:
$ umask 002 $ touch shared-project-file.txt $ ls -l shared-project-file.txt -rw-rw-r-- 1 alex developers 0 Sep 15 11:45 shared-project-file.txt
Both owner and group can read/write. Others can only read. This prevents the “I can’t edit Bob’s files” problem.
CI/CD Pipeline Security
DevOps pipelines are notorious for creating files with insecure permissions. I’ve seen GitHub Actions runners create artifacts readable by all users on the build server.
In your pipeline config, explicitly set umask:
# .github/workflows/build.yml
- name: Build artifacts
run: |
umask 077
./build.sh
tar czf release.tar.gz dist/This ensures your build artifacts don’t leak to other users on shared runners.
Common umask Mistakes and How to Avoid Them
After years of troubleshooting permission issues, these are the errors I see most often:
Mistake 1: Setting umask too permissive (000)
Some folks think umask 000 makes life easier. It does—for attackers. Every file you create becomes world-writable. Never do this in production.
Mistake 2: Setting umask too restrictive (077) in collaborative environments
The opposite problem. Your team can’t access shared files, workflows break, frustration ensues. Match your umask to your environment.
Mistake 3: Forgetting umask is a mask, not direct permissions
New admins often think “umask 644 will give me 644 permissions.” Nope. umask 644 would remove 644 from the base permissions, giving you 022 for files (not what you wanted).
Mistake 4: Not verifying changes
Always test after changing umask:
$ umask 027 $ touch test.txt $ mkdir test-dir $ ls -ld test.txt test-dir -rw-r----- 1 alex alex 0 Sep 15 12:05 test.txt drwxr-x--- 2 alex alex 4096 Sep 15 12:05 test-dir
If the permissions don’t match expectations, you caught it early.
Mistake 5: Different umask in shell vs scripts
Your interactive shell might have umask 022, but your cron scripts might run with 077. This creates confusing permission mismatches. Always set umask explicitly in scripts.
umask Security Best Practices for 2025
Based on current security trends and compliance requirements, here’s what I recommend:
Standard workstations: umask 022
Balanced permissions. Files are readable by all, writable only by owner. Good for single-user systems.
Multi-user servers: umask 027
More restrictive. Others get no permissions. Group members can read. Recommended by the CIS Security Benchmarks.
High-security environments: umask 077
Maximum privacy. Only the owner has any permissions. Use for systems handling sensitive data.
Shared development: umask 002
Collaborative-friendly. Group members can edit each other’s work.
Additional best practices:
- Audit user umask settings: Check
~/.bashrcfiles during security reviews - Set explicit umask in CI/CD: Don’t rely on runner defaults
- Document your umask policy: Make it clear to your team why you’ve chosen specific values
- Regular permission audits: Use
findto locate world-writable files created accidentally - Balance security and usability: The most secure umask is worthless if users work around it
For troubleshooting permission-related issues after deployment, you can check system logs with journalctl to see if permission denied errors are occurring.
The POSIX umask specification defines the standard behavior across Unix-like systems, so these practices apply whether you’re on Linux, BSD, or macOS.
Remember: umask is just one layer of security. Combine it with proper firewall configuration, regular updates, and the principle of least privilege for defense in depth.
The bottom line? Set your umask deliberately, test it thoroughly, and make it permanent. Your future self—and your security team—will thank you.







