fix: only download covers from http(s) URLs, never local paths #18
Loading…
Reference in a new issue
No description provided.
Delete branch "jtk/cover-url-local-path"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #5 (critical): any logged-in user could post
book[cover_url]=/etc/passwd(or a config/env file) to/books/add-from-lookup,scan_barcodeorbatch_add, and the server copied the file into/uploads/covers/<uuid>.jpg, which is served without auth.Changes
Storage.download_and_store_cover/1only acceptshttp/httpsURLs with a host. Local paths,file://, other schemes and non-strings return{:error, :unsupported_url}and log a warning.Storage.store_synced_cover/1, used only byExternalLibrarySync: http(s) URLs are downloaded, anything else must be a regular file (checked withlstat, so no symlinks) inside the configured Calibrelibrary_path.store_local_cover/2now takes the allowed roots.Storage.store_cover/2sniffs magic bytes (JPEG/PNG/GIF/WebP) and refuses anything else (:not_an_image); the stored type and extension come from the bytes, not the declared content type or the upload's filename.inspected (interpolating a Req exception struct would have raised).SSRF (#6) is a separate PR on top of this.
Tests
test/fuzzy_catalog/storage_test.exs(local paths and non-http schemes refused, non-images refused, Calibre covers inside the library accepted,.., sibling-prefix dirs and symlinks refused) and a controller test that postscover_url=/etc/passwdand checks no cover is stored.mix precommit: 172 tests pass.Review by Nye (PR review / audit) — APPROVE
download_and_store_coveronly takes http(s) URLs with a non-empty host; thecover_urlpath inbook_controllercan no longer reach the filesystem.store_synced_cover, confined tocalibre.library_path(same config sourceCalibreProvideruses, so no behaviour gap).Path.expandnormalises...store_coversniffs magic bytes, so a non-image can't be stored.Non-blocking follow-up (filed as low):
lstatonly checks the final path component, so a symlinked directory inside the Calibre library could still point outside it. Fix later by resolving the real path. The library is admin-controlled, so not a blocker.