Skip to content

Security: socrasteeze/image-cull

Security

SECURITY.md

Security

Threat model, stated plainly

cull has no authentication. It is built to run on a private network you control — a Tailscale tailnet or a home LAN — where the network itself is the security boundary. There are no users, no passwords, no sessions, and no authorization checks anywhere in the API.

The container binds 0.0.0.0 so it is reachable from other devices on that network. That is deliberate, and it is safe only under the assumption above.

Anyone who can reach the port has full control of your image library. They can browse every image, read embedded prompts and metadata, move files to _trash, collapse duplicates, and — if update_enabled is on — make the NAS download and run a new build of the application.

Do not expose cull to the internet

Concretely, do not:

  • port-forward 8080 (or whatever you set) from your router,
  • publish the port on a VPS with a public IP,
  • put it behind a plain reverse proxy with no authentication,
  • or attach it to an untrusted or shared network (a coworking space, a hotel, a shared hosting VLAN).

If you need access from outside your home, use a VPN or an overlay network such as Tailscale, WireGuard, or ZeroTier. That is the intended deployment, and it keeps the boundary where the design expects it.

If you genuinely must expose it more widely, put an authenticating reverse proxy in front (Caddy with basic auth, Authelia, oauth2-proxy, Cloudflare Access, or similar). cull will not do it for you, and it does not pretend to.

The destructive surface, for anyone auditing

These endpoints change or destroy data. None of them require credentials:

Endpoint What it can do
POST /action (trash) moves image files into a _trash sibling directory
POST /duplicates/collapse* moves files into a _duplicates quarantine
POST /duplicates/quarantined/purge moves the quarantine into _trash
POST /rescan forces a full re-index (expensive, not destructive)
POST /update asks the NAS-side watcher to rebuild and restart the app

Triage is reversible by design — trash is a file move into _trash, not an unlink, and restore puts it back. cull never calls unlink on your images. Emptying _trash is left to you, deliberately.

POST /update is the sharpest edge, because it causes code to be downloaded and executed on the NAS. It is off by default; it only works when you set update_enabled: true and run the host-side watcher. If that combination makes you uncomfortable, leave it off — everything else works without it.

Reporting a vulnerability

Please use GitHub's private vulnerability reporting (Security → Report a vulnerability) rather than opening a public issue, so a fix can land before details are public.

Since the project assumes a trusted network, "no auth on the API" is a known and documented design decision, not a vulnerability. Reports that are useful: path traversal that escapes the configured library root, ways to make cull delete or overwrite files outside it, command injection into the update path, or anything that turns a request into code execution.

There aren't any published security advisories