Ubuntu · Accounts & authentication

Set a restrictive default umask for login sessions

When it fails: New files are readable by every local user by default. With the Ubuntu default umask, documents, exports and logs created by users and root are world-readable.

CB-UBU-AUTH-019lowactiveautomatedautomated fixprofile core

As released in v0.1.2 (beta). Current state.

Description

The umask removes permission bits from every file and directory a process creates. Ubuntu login sessions get 022 (files 644, everyone can read them), and pam_umask with USERGROUPS_ENAB yes even gives 002 to regular users who have their own group. This control sets {{ umask }} from /etc/profile.d/, which applies to the login shells of every user, root included.

Services started by systemd do not read /etc/profile; set their umask with UMask= in their unit.

Rationale

Users and administrators regularly create files with sensitive content (exports, dumps, configuration copies) in their home or in /tmp. A restrictive umask keeps them private unless someone opens them on purpose.

Impact

Files created in shared directories are no longer readable by other users. Teams that share files through a common group need chmod g+r or a setgid group directory.

Setting

Location/etc/profile.d/60-cirsec-umask.sh
Default022
Recommended{{ umask }}

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
umaskenum. Default umask of login shells.027027077027027one of 027, 077

The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.

Audit

Run su -s /bin/sh -l nobody -c umask and su -l root -c umask. Both must print 0{{ umask }} (or a stricter value).

Automated: every check must pass. Scanners report each check by its id.

user

Umask of a login shell for a regular account.

script: |
  u=$(su -s /bin/sh -l nobody -c umask 2>/dev/null | tail -n 1) || exit 3
  echo "nobody login umask: $u"
  [ $(( 0$u & 0$CB_UMASK )) -eq $(( 0$CB_UMASK )) ]

root

Umask of a root login shell.

script: |
  u=$(su -l root -c umask 2>/dev/null | tail -n 1) || exit 3
  echo "root login umask: $u"
  [ $(( 0$u & 0$CB_UMASK )) -eq $(( 0$CB_UMASK )) ]

Remediation

Create /etc/profile.d/60-cirsec-umask.sh containing umask {{ umask }}. New login sessions pick it up.

Restartusers must log in again
Disruptionlow

Rollback

Delete /etc/profile.d/60-cirsec-umask.sh.

profile

f=/etc/profile.d/60-cirsec-umask.sh
cb_backup "$f"
printf '%s\n' '# Written by CIRSEC Baselines CB-UBU-AUTH-019' "umask $CB_UMASK" >"$f"
chmod 644 "$f"

Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.

References

Mappings

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic. Fails on a fresh install (022); login shells of nobody and root get 027 in core, 077 in server-hardened; kept after reboot.
Verified2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic. Fails on a fresh install (022); login shells of nobody and root get 027 in core, 077 in server-hardened; kept after reboot.
Verified2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic. Fails on a fresh install (022); login shells of nobody and root get 027 in core, 077 in server-hardened; kept after reboot.
Verified2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic. Fails on a fresh install (022); login shells of nobody and root get 027 in core, 077 in server-hardened; kept after reboot.
Introduced inv0.1.0
Created, updated2026-10-19, 2026-10-19
Translationsfr