PhoenixKit.Modules.Storage.Sniff (phoenix_kit v2.45.0)

Copy Markdown View Source

What a file is, read from its first bytes rather than from its name or the browser's Content-Type — both of which are the uploader's claims.

Two uses:

  • at upload, Storage lets a sniffed raster image type overrule the claimed one, and stops a file that claims to be a raster image but is not from being handed to the image pipeline;
  • before ImageMagick touches a file, ImageProcessor pins the decoder to the sniffed raster format (png:/tmp/x), so a file can never be read by a coder nobody meant to run.

Only the formats in raster_formats/0 are ever given to ImageMagick. SVG, PDF, PostScript/EPS, MVG, MSL and the rest reach their decoders through delegates (librsvg, Ghostscript…) with a long history of command injection and memory-safety bugs; they are recognised here so they can be refused, never pinned.

Summary

Functions

The ImageMagick coder name that pins decoding to format ("png" → png:/path), or nil for anything that must not reach ImageMagick.

The MIME type for a sniffed format.

Whether format is one ImageMagick may be given.

The raster formats ImageMagick may decode, each with a pinned coder.

Reads the first bytes of the file at path and names its format. :unknown for anything unrecognised or unreadable.

sniff/1 over bytes already in memory (the first ~512 are enough).

Types

format()

@type format() ::
  :png
  | :jpeg
  | :gif
  | :webp
  | :tiff
  | :bmp
  | :ico
  | :heic
  | :avif
  | :svg
  | :pdf
  | :postscript
  | :zip
  | :mp4
  | :quicktime
  | :webm
  | :mp3
  | :wav
  | :ogg

result()

@type result() :: {:ok, %{format: format(), mime: String.t()}} | :unknown

Functions

magick_coder(arg1)

@spec magick_coder(format() | nil) :: String.t() | nil

The ImageMagick coder name that pins decoding to format ("png" → png:/path), or nil for anything that must not reach ImageMagick.

mime(format)

@spec mime(format()) :: String.t()

The MIME type for a sniffed format.

raster?(format)

@spec raster?(format() | nil) :: boolean()

Whether format is one ImageMagick may be given.

raster_formats()

@spec raster_formats() :: [format()]

The raster formats ImageMagick may decode, each with a pinned coder.

sniff(path)

@spec sniff(Path.t()) :: result()

Reads the first bytes of the file at path and names its format. :unknown for anything unrecognised or unreadable.

sniff_binary(head)

@spec sniff_binary(binary()) :: result()

sniff/1 over bytes already in memory (the first ~512 are enough).