An update: the CPython makedirs fix is merged, with a backport approved for 3.15beta2. I pushed this forward at the PyCon US 2026 sprints (I met with Greg and we resolved conflicts and got it merged
).
This makes the choice concrete: if Django adopts stdlib semantics, the vendored code disappears entirely. If not, Django must add explicit chmod calls on top of the new makedirs: the same complexity, permanently. This would likely mean a second for-loop to set perms (which I very very much would like to avoid).
@KenWhitesell On the “I set it, I expect exactly that” concern: umask can only remove bits, never add them, so a typical umask of 0o022 leaves 0o755 unchanged. The only case it differs is when a sysadmin has deliberately set a more restrictive umask, in which case I still think that honoring it is correct (this is Shai’s main point).
Also worth noting: in all cases (before the CVE fix, after it, and going forward) Django never changes permissions on existing directories. A pre-existing directory in the upload path keeps whatever permissions it already has, regardless of FILE_UPLOAD_DIRECTORY_PERMISSIONS. So the setting was never a guarantee of exact permissions across the board; it was always a ceiling. Adopting umask semantics simply makes that explicit (we would change 6.2+ so it uses CPython’s makedirs and adjust our docs).
Given all of the above, I find it hard to justify maintaining a vendored copy of the fixed makedirs.