Skip to content

Image upload handler reads entire file into memory with no enforced size limit #47

@windoze95

Description

@windoze95

Description

In internal/handlers/image.go:66, io.ReadAll(file) reads the entire uploaded file into a single in-memory buffer:

fileBytes, err := io.ReadAll(file)

The header.Size check on line 60 relies on the client-supplied Content-Length header value, which can be trivially spoofed — an attacker can set a small Content-Length while streaming gigabytes of data. This creates an OOM denial-of-service vector.

Contrast with Safe Pattern

internal/handlers/import.go:74 correctly uses:

body, err := io.ReadAll(io.LimitReader(resp.Body, 10*1024*1024))

Impact

  • A single authenticated request can exhaust server memory
  • With multiple concurrent uploads, can crash the service

Suggested Fix

const maxImageBytes = 10 * 1024 * 1024 // 10 MB, matching existing limit logic
limited := io.LimitReader(file, maxImageBytes+1)
fileBytes, err := io.ReadAll(limited)
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read file"})
    return
}
if int64(len(fileBytes)) > maxImageBytes {
    c.JSON(http.StatusBadRequest, gin.H{"error": "file exceeds maximum size"})
    return
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions