Skip to content

File and Directory Permissions

Inspect parent directories, ACLs, mount options, file capabilities, and SUID/SGID in addition to the target file. If a root process reads the path, investigate further under Writable Paths Read by root.

Additional check examples:

Terminal window
namei -l <path>
stat <path>
ls -la <path>
findmnt
getfacl <path>
getcap <file>
getcap -r / 2>/dev/null
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
  • Purpose: Check owners, groups, modes, ACLs, symlinks, mount options, capabilities, and SUID/SGID.
  • Prerequisites: Searching every filesystem is expensive. Start with /opt, /srv, /var/www, /home/<user>, /etc/systemd/system, /usr/local/bin, and application directories.
  • What to inspect: Writable parent directories, nosuid, noexec, nodev, bind mounts, and user-writable paths read by root processes.
  • Expected output: drwxrwxr-x root <group> ... <app>/plugins, /tmp without nosuid, or a shared path mounted with bind.
  • Interpretation: Even when root owns a file, a writable parent directory may allow replacement, symlinks, or races. A SUID shell on a nosuid mount will not work.
  • If a check fails: Inspect ACLs, supplementary groups, UID/GID inside containers, mount namespaces, and resolved symlink targets.
  • Alternative commands: find <DIR> -maxdepth 4 -writable -ls, find <DIR> -xtype l -ls, readlink -f <path>.
  • State change: Read-only. find / creates load and many Permission denied messages; narrow the scope.

High-priority locations:

Terminal window
find /opt /srv /var/www /usr/local -maxdepth 5 -type d -writable -ls 2>/dev/null
find /opt /srv /var/www /usr/local -maxdepth 5 -type f -writable -ls 2>/dev/null
find /home -maxdepth 4 -type f \( -name '*.conf' -o -name '*.env' \) 2>/dev/null

Shared mounts also affect container boundaries. Check them alongside findmnt in Containers and Namespaces.

  • A path read by root becomes a privilege boundary if symlinks, writable parents, races, or archive extraction affect it.
  • SUID binaries do not work on nosuid mounts. bash drops privileges on execution without -p.
  • Record getcap results separately from the process CapEff checked under Containers and Namespaces. File capabilities and a process’s effective capabilities are different.

Examples where permission differences create boundaries:

  • If a script running as root calls site.addsitedir() on a group-writable plugin directory, that group can write to the import path.
  • A symlink into a log directory may have multiple levels. A privileged viewing process might read the second-level target as root.
  • On a mount shared by container and host, chmod inside the container can change whether a host user may write.
  • If the Web process user can write to a theme or public directory, writing there can lead to code execution as that user.
  • If output is saved as a script in the document root of a development HTTP server running as root, it executes with that process’s privileges.

The flow by which a privileged process reads these paths is diagrammed under Trust Boundaries in Custom Code.