Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

Audit File Permissions Across a Project in Python

Walks through every file and directory in a project tree and prints POSIX permissions plus owner UID.

Easy Python 3.9+ Jun 28, 2026 Files & data 2 views 0 copies

Python code

25 lines
Python 3.9+
import os
import stat
from pathlib import Path

def audit_file_permissions(project_root):
    """Walk through project_root and print path, owner, and permissions for every file."""
    results = []
    for root, dirs, files in os.walk(project_root):
        for name in files + dirs:
            full_path = os.path.join(root, name)
            try:
                st = os.stat(full_path)
                mode = st.st_mode
                perms = stat.filemode(mode)
                results.append((full_path, st.st_uid, perms))
            except OSError:
                continue
    return results

if __name__ == "__main__":
    # Example usage: audit the current working directory
    project_path = Path.cwd()
    entries = audit_file_permissions(project_path)
    for path, uid, perms in entries:
        print(f"{perms} UID={uid} {path}")

Output

stdout
drwxr-xr-x UID=1001 /home/user/project
-rw-r--r-- UID=1001 /home/user/project/README.md
-rw-r--r-- UID=1001 /home/user/project/main.py
drwx------ UID=1002 /home/user/project/secrets

How it works

The script uses os.walk to recursively traverse the project tree. For each entry (file or directory), it calls os.stat to retrieve the file's status block. stat.filemode converts the raw mode bits into the familiar rwx string. The result is a list of tuples that can be printed or further processed, e.g. to detect files with overly permissive settings.

The try/except OSError skips entries that cannot be stat'd (broken symlinks, permission denied) so the audit continues without crashing.

Common mistakes

  • Forgetting to handle permission errors when walking subdirectories the user can't enter.
  • Using `os.stat` on symlinks gives the target's mode; use `os.lstat` if you need the link's own mode.
  • Assuming `st_uid` is a username string; it's an integer UID that requires `pwd.getpwuid` for a human name.
  • Not filtering out directories when only file permissions matter.

Variations

  1. Use `pathlib.Path.rglob('*')` with `Path.stat()` for a more modern, object-oriented approach.
  2. Add `pwd.getpwuid(st_uid).pw_name` to display human-readable usernames instead of numeric UIDs.

Real-world use cases

  • Pre-deployment CI check that no file in the release artifact has world-writable permissions.
  • Security scan after a data breach to identify files owned by unexpected UIDs across a web application.
  • Onboarding script that verifies all project files have consistent owner/group before pushing to production.

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.