Opened 58 minutes ago
#37401 assigned Cleanup/optimization
Made `FILE_UPLOAD_DIRECTORY_PERMISSIONS` respect the process umask to remove vendored `makedirs`
| Reported by: | Natalia Bidart | Owned by: | Natalia Bidart |
|---|---|---|---|
| Component: | File uploads/storage | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Following the forum discussion and agreement from the Steering Council and the Security Team, directories created via django.utils._os.safe_makedirs() should be subject to the process umask, matching the semantics of os.mkdir() and os.makedirs(). This affects FileSystemStorage when FILE_UPLOAD_DIRECTORY_PERMISSIONS (or directory_permissions_mode) is set, and FileBasedCache (which uses a fixed 0o700).
Currently, the vendored makedirs() added in the fix for CVE-2026-25674 calls os.chmod() after each os.mkdir() to force the exact mode, ignoring the umask (a behavior dating back to #13518). Since the umask can only remove bits, resulting permissions may be more restrictive than configured, never more permissive. Common combinations such as 0o755 with a 0o022 umask are unchanged, and existing directories remain untouched.
Python 3.15 added parent_mode to os.makedirs() (python/cpython#86533), so safe_makedirs() can use it directly on 3.15+, keeping the vendored implementation (without the extra chmod()) for older Python versions until they are dropped.
The change applies on Django 6.2+ for all supported Python versions and will be documented as a backwards incompatible change in the 6.2 release notes, with updates to the FILE_UPLOAD_DIRECTORY_PERMISSIONS and FileSystemStorage.directory_permissions_mode docs. FILE_UPLOAD_PERMISSIONS is out of scope: it is applied via os.chmod() after writing and remains exact.