Skip to content

SaveUploadedFile: unexpected chmod on existing directories (breaks /tmp usage) #4622

@phplego

Description

@phplego

Description

After upgrading from v1.10.1 to v1.12.0, Context.SaveUploadedFile started to fail when saving files directly into existing system directories like /tmp.

The failure happens due to an attempt to call os.Chmod on the target directory, even if it already exists and is not owned by the process.

Relevant code:
https://github.com/gin-gonic/gin/blob/v1.12.0/context.go#L734

Reproduction

file, _ := c.FormFile("file")

// Saving directly into /tmp
err := c.SaveUploadedFile(file, "/tmp/test.txt")
if err != nil {
  panic(err)
}

Actual behavior

The call fails with:

chmod /tmp: operation not permitted

Expected behavior

If the directory already exists, especially for system directories like /tmp, SaveUploadedFile should not attempt to modify its permissions.

The previous behavior (v1.10.1) only used os.MkdirAll, which does not change permissions on existing directories.

Impact

This is a breaking change for common usage patterns such as:

  • saving files to /tmp/<filename>
  • writing into pre-existing directories managed by the OS or container runtime

Context

This behavior appears to be introduced together with the change that allows specifying permissions for created directories (see #4068). However, applying chmod unconditionally also affects already existing directories.

Suggested fix

Only apply os.Chmod when the directory is newly created, or make it optional.

For example:

  • skip chmod if directory already exists
  • or provide a flag to control this behavior

Additional notes

This change is not mentioned as breaking in release notes, but it alters previously working behavior.

Gin Version

v1.12.0

Can you reproduce the bug?

Yes

Source Code

file, _ := c.FormFile("file")

// Saving directly into /tmp
err := c.SaveUploadedFile(file, "/tmp/test.txt")
if err != nil {
   panic(err)
}

Go Version

1.26.1

Operating System

linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugFound something you weren't expecting? Report it here!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions